mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-22 10:05:32 +01:00
Get g3dlib, zlib and jemalloc to build again
--HG-- branch : trunk rename : opt/cleanup/tab2spaces.sh => contrib/cleanup/tab2spaces.sh rename : opt/cleanup/whitespace.sh => contrib/cleanup/whitespace.sh rename : opt/conf_merge/README => contrib/conf_merge/README rename : opt/conf_merge/index.php => contrib/conf_merge/index.php rename : opt/conf_merge/merge.php => contrib/conf_merge/merge.php rename : doc/AuctionHouseBot.txt => docs/AuctionHouseBot.txt rename : doc/DocStructure.dox => docs/DocStructure.dox rename : doc/Doxyfile.in => docs/Doxyfile.in rename : doc/EventAI.txt => docs/EventAI.txt rename : doc/HowToScript.txt => docs/HowToScript.txt rename : doc/TextTables.txt => docs/TextTables.txt rename : doc/UnixInstall.txt => docs/UnixInstall.txt rename : externals/jemalloc/include/internal/arena.h => externals/jemalloc/jemalloc/internal/arena.h rename : externals/jemalloc/include/internal/base.h => externals/jemalloc/jemalloc/internal/base.h rename : externals/jemalloc/include/internal/chunk.h => externals/jemalloc/jemalloc/internal/chunk.h rename : externals/jemalloc/include/internal/chunk_dss.h => externals/jemalloc/jemalloc/internal/chunk_dss.h rename : externals/jemalloc/include/internal/chunk_mmap.h => externals/jemalloc/jemalloc/internal/chunk_mmap.h rename : externals/jemalloc/include/internal/chunk_swap.h => externals/jemalloc/jemalloc/internal/chunk_swap.h rename : externals/jemalloc/include/internal/ckh.h => externals/jemalloc/jemalloc/internal/ckh.h rename : externals/jemalloc/include/internal/ctl.h => externals/jemalloc/jemalloc/internal/ctl.h rename : externals/jemalloc/include/internal/extent.h => externals/jemalloc/jemalloc/internal/extent.h rename : externals/jemalloc/include/internal/hash.h => externals/jemalloc/jemalloc/internal/hash.h rename : externals/jemalloc/include/internal/huge.h => externals/jemalloc/jemalloc/internal/huge.h rename : externals/jemalloc/include/internal/jemalloc_internal.h => externals/jemalloc/jemalloc/internal/jemalloc_internal.h rename : externals/jemalloc/include/internal/jemalloc_internal.h.in => externals/jemalloc/jemalloc/internal/jemalloc_internal.h.in rename : externals/jemalloc/include/internal/mb.h => externals/jemalloc/jemalloc/internal/mb.h rename : externals/jemalloc/include/internal/mutex.h => externals/jemalloc/jemalloc/internal/mutex.h rename : externals/jemalloc/include/internal/prof.h => externals/jemalloc/jemalloc/internal/prof.h rename : externals/jemalloc/include/internal/ql.h => externals/jemalloc/jemalloc/internal/ql.h rename : externals/jemalloc/include/internal/qr.h => externals/jemalloc/jemalloc/internal/qr.h rename : externals/jemalloc/include/internal/rb.h => externals/jemalloc/jemalloc/internal/rb.h rename : externals/jemalloc/include/internal/stats.h => externals/jemalloc/jemalloc/internal/stats.h rename : externals/jemalloc/include/internal/tcache.h => externals/jemalloc/jemalloc/internal/tcache.h rename : externals/jemalloc/include/internal/totally_not_p_r_n.h => externals/jemalloc/jemalloc/internal/totally_not_p_r_n.h rename : externals/jemalloc/include/jemalloc.h => externals/jemalloc/jemalloc/jemalloc.h rename : externals/jemalloc/include/jemalloc.h.in => externals/jemalloc/jemalloc/jemalloc.h.in rename : externals/jemalloc/include/jemalloc_defs.h => externals/jemalloc/jemalloc/jemalloc_defs.h rename : externals/jemalloc/include/jemalloc_defs.h.in => externals/jemalloc/jemalloc/jemalloc_defs.h.in
This commit is contained in:
158
CMakeLists.txt
158
CMakeLists.txt
@@ -12,19 +12,22 @@ include(cmake/PCH.cmake)
|
||||
# Force out-of-source build
|
||||
string(COMPARE EQUAL "${CMAKE_SOURCE_DIR}" "${CMAKE_BINARY_DIR}" BUILDING_IN_SOURCE)
|
||||
if(BUILDING_IN_SOURCE)
|
||||
message(FATAL_ERROR "This project requires an out of source build. Remove the file 'CMakeCache.txt' found in this directory before continuing, and create a separate build directory and run 'cmake path_to_project [options]' from there.")
|
||||
message(FATAL_ERROR "This project requires an out of source build. Remove the file 'CMakeCache.txt' found in this directory before continuing, and create a separate build directory and run 'cmake path_to_project [options]' from there.")
|
||||
endif(BUILDING_IN_SOURCE)
|
||||
|
||||
# Select the Release build configuration by default.
|
||||
if(NOT CMAKE_BUILD_TYPE)
|
||||
set(CMAKE_BUILD_TYPE "Release")
|
||||
set(CMAKE_BUILD_TYPE "Release")
|
||||
endif(NOT CMAKE_BUILD_TYPE)
|
||||
|
||||
CONFIGURE_FILE(
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
|
||||
IMMEDIATE @ONLY)
|
||||
add_custom_target(uninstall "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake")
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
|
||||
IMMEDIATE @ONLY)
|
||||
|
||||
add_custom_target(uninstall
|
||||
"${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
|
||||
)
|
||||
|
||||
option(CENTOS "CENTOS" 0)
|
||||
option(DO_CLI "With CLI" 1)
|
||||
@@ -38,49 +41,49 @@ option(DO_TOOLS "Compile tools" 0)
|
||||
option(DO_WARN "Enable all compile warnings" 0)
|
||||
|
||||
set(GENREV_SRC
|
||||
src/genrevision/genrevision.cpp
|
||||
src/genrevision/genrevision.cpp
|
||||
)
|
||||
|
||||
if(DO_DEBUG)
|
||||
add_executable(genrev
|
||||
add_executable(genrev
|
||||
${GENREV_SRC}
|
||||
)
|
||||
add_custom_target("revision.h" ALL
|
||||
COMMAND "${CMAKE_BINARY_DIR}/genrev"
|
||||
${CMAKE_SOURCE_DIR}
|
||||
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}/src/shared"
|
||||
DEPENDS genrev
|
||||
)
|
||||
)
|
||||
add_custom_target("revision.h" ALL
|
||||
COMMAND "${CMAKE_BINARY_DIR}/genrev"
|
||||
${CMAKE_SOURCE_DIR}
|
||||
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}/src/server/shared"
|
||||
DEPENDS genrev
|
||||
)
|
||||
else (DO_DEBUG)
|
||||
add_executable(genrev
|
||||
add_executable(genrev
|
||||
${GENREV_SRC}
|
||||
)
|
||||
add_custom_target("revision.h" ALL
|
||||
COMMAND "${CMAKE_BINARY_DIR}/genrev"
|
||||
${CMAKE_SOURCE_DIR}
|
||||
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}/src/server/shared"
|
||||
DEPENDS genrev
|
||||
)
|
||||
)
|
||||
add_custom_target("revision.h" ALL
|
||||
COMMAND "${CMAKE_BINARY_DIR}/genrev"
|
||||
${CMAKE_SOURCE_DIR}
|
||||
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}/src/server/shared"
|
||||
DEPENDS genrev
|
||||
)
|
||||
endif(DO_DEBUG)
|
||||
|
||||
|
||||
execute_process(
|
||||
COMMAND hg tip --template {rev}
|
||||
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
||||
OUTPUT_VARIABLE HG_REVISION
|
||||
COMMAND hg tip --template {rev}
|
||||
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
||||
OUTPUT_VARIABLE HG_REVISION
|
||||
)
|
||||
|
||||
message("* TrinityCore revision: ${HG_REVISION}")
|
||||
|
||||
if(PREFIX)
|
||||
set(CMAKE_INSTALL_PREFIX ${PREFIX})
|
||||
set(CMAKE_INSTALL_PREFIX ${PREFIX})
|
||||
endif(PREFIX)
|
||||
|
||||
if(CONF_DIR)
|
||||
|
||||
else(CONF_DIR)
|
||||
set(CONF_DIR ${PREFIX}/etc)
|
||||
set(CONF_DIR ${PREFIX}/etc)
|
||||
endif(CONF_DIR)
|
||||
|
||||
set(LIBSDIR ${CMAKE_INSTALL_PREFIX}/lib)
|
||||
|
||||
message("* Will install to: ${CMAKE_INSTALL_PREFIX}")
|
||||
@@ -91,98 +94,97 @@ find_library(SSLLIB NAMES ssl DOC "SSL library")
|
||||
find_library(ZLIB z "Zlib library")
|
||||
|
||||
if(DO_MYSQL)
|
||||
message("* With MySQL")
|
||||
FIND_MYSQL()
|
||||
ADD_DEFINITIONS(-DDO_MYSQL)
|
||||
message("* With MySQL")
|
||||
FIND_MYSQL()
|
||||
ADD_DEFINITIONS(-DDO_MYSQL)
|
||||
endif(DO_MYSQL)
|
||||
|
||||
if(DO_SCRIPTS)
|
||||
message("* With Trinity Scripts")
|
||||
ADD_DEFINITIONS(-DDO_SCRIPTS)
|
||||
add_definitions(-D_TRINITY_SCRIPT_CONFIG='"${CONF_DIR}/trinitycore.conf"')
|
||||
message("* With Trinity Scripts")
|
||||
ADD_DEFINITIONS(-DDO_SCRIPTS)
|
||||
add_definitions(-D_TRINITY_SCRIPT_CONFIG='"${CONF_DIR}/trinitycore.conf"')
|
||||
else (DO_SCRIPTS)
|
||||
message("* Without Trinity Scripts")
|
||||
message("* Without Trinity Scripts")
|
||||
endif(DO_SCRIPTS)
|
||||
|
||||
message("-- Miscellaneus options:")
|
||||
|
||||
if(DO_CLI)
|
||||
message("* With CLI")
|
||||
add_definitions(-DENABLE_CLI)
|
||||
message("* With CLI")
|
||||
add_definitions(-DENABLE_CLI)
|
||||
else (DO_CLI)
|
||||
message(* Without CLI)
|
||||
message(* Without CLI)
|
||||
endif(DO_CLI)
|
||||
|
||||
if(DO_RA)
|
||||
message("* With RA")
|
||||
add_definitions(-DENABLE_RA)
|
||||
message("* With RA")
|
||||
add_definitions(-DENABLE_RA)
|
||||
else(DO_RA)
|
||||
message("* Without RA")
|
||||
message("* Without RA")
|
||||
endif(DO_RA)
|
||||
|
||||
if(DO_DEBUG)
|
||||
message("* Debug mode ON")
|
||||
add_definitions(-g -DTRINITY_DEBUG)
|
||||
message("* Debug mode ON")
|
||||
add_definitions(-g -DTRINITY_DEBUG)
|
||||
endif(DO_DEBUG)
|
||||
|
||||
if(DO_WARN)
|
||||
message("* All warnings mode")
|
||||
add_definitions(-Wall -Wfatal-errors -Wextra)
|
||||
message("* All warnings mode")
|
||||
add_definitions(-Wall -Wfatal-errors -Wextra)
|
||||
endif(DO_WARN)
|
||||
|
||||
if(DO_SQL)
|
||||
message("* Installing SQL files")
|
||||
message("* Installing SQL files")
|
||||
else (DO_SQL)
|
||||
message("* NOT installing SQL files")
|
||||
message("* NOT installing SQL files")
|
||||
endif(DO_SQL)
|
||||
|
||||
if(DO_PCH)
|
||||
message("* Using precompiled headers")
|
||||
message("* Using precompiled headers")
|
||||
else (DO_PCH)
|
||||
message("* NOT using precompiled headers")
|
||||
message("* NOT using precompiled headers")
|
||||
endif(DO_PCH)
|
||||
|
||||
if(DO_TOOLS)
|
||||
message("* With Tools")
|
||||
message("* With Tools")
|
||||
else (DO_TOOLS)
|
||||
message("* Without Tools")
|
||||
message("* Without Tools")
|
||||
endif(DO_TOOLS)
|
||||
|
||||
|
||||
if(UNIX)
|
||||
if(CENTOS)
|
||||
add_definitions(-DCENTOS)
|
||||
message("* Building with termcap")
|
||||
FIND_TERMCAP()
|
||||
else(CENTOS)
|
||||
message("* Building with readline")
|
||||
FIND_READLINE()
|
||||
endif(CENTOS)
|
||||
if(CENTOS)
|
||||
add_definitions(-DCENTOS)
|
||||
message("* Building with termcap")
|
||||
FIND_TERMCAP()
|
||||
else(CENTOS)
|
||||
message("* Building with readline")
|
||||
FIND_READLINE()
|
||||
endif(CENTOS)
|
||||
endif(UNIX)
|
||||
|
||||
FIND_ACE(ACE)
|
||||
if(ACE_FOUND)
|
||||
message(STATUS "Found ACE library: ${ACE_LIBRARY}")
|
||||
message(STATUS "Include dir is: ${ACE_INCLUDE_DIR}")
|
||||
message(STATUS "Found ACE library: ${ACE_LIBRARY}")
|
||||
message(STATUS "Include dir is: ${ACE_INCLUDE_DIR}")
|
||||
else(ACE_FOUND)
|
||||
message(SEND_ERROR "** ACE library not found! Trinity Core cannot be compiled!")
|
||||
message(SEND_ERROR "** Please build ACE from http://www.cs.wustl.edu/~schmidt/ACE.html")
|
||||
#For now remove msg about install from repo, as ubuntu/debian don't have needed ver in repos.
|
||||
#message(SEND_ERROR "** your distro may provide a binary for ACE e.g. for ubuntu try apt-get install libace-dev")
|
||||
return()
|
||||
#set(BUILD_ACE 1)
|
||||
#set(ACE_INCLUDE_DIR "${CMAKE_SOURCE_DIR}/dep/ACE_wrappers ${CMAKE_BINARY_DIR}/dep/ACE_wrappers")
|
||||
#set(ACE_LIBRARY ACE)
|
||||
#message(STATUS "I will try to build ACE from: ${ACE_INCLUDE_DIR}")
|
||||
#message(STATUS "And link using: ${ACE_LIBRARY}")
|
||||
message(SEND_ERROR "** ACE library not found! Trinity Core cannot be compiled!")
|
||||
message(SEND_ERROR "** Please build ACE from http://www.cs.wustl.edu/~schmidt/ACE.html")
|
||||
#For now remove msg about install from repo, as ubuntu/debian don't have needed ver in repos.
|
||||
#message(SEND_ERROR "** your distro may provide a binary for ACE e.g. for ubuntu try apt-get install libace-dev")
|
||||
return()
|
||||
#set(BUILD_ACE 1)
|
||||
#set(ACE_INCLUDE_DIR "${CMAKE_SOURCE_DIR}/dep/ACE_wrappers ${CMAKE_BINARY_DIR}/dep/ACE_wrappers")
|
||||
#set(ACE_LIBRARY ACE)
|
||||
#message(STATUS "I will try to build ACE from: ${ACE_INCLUDE_DIR}")
|
||||
#message(STATUS "And link using: ${ACE_LIBRARY}")
|
||||
endif(ACE_FOUND)
|
||||
|
||||
#somehow line below don't work. so for now change it to if exist
|
||||
#check_include_files(${ACE_INCLUDE_DIR}/ace/Stack_Trace.h HAVE_ACE_STACK_TRACE_H)
|
||||
if(EXISTS ${ACE_INCLUDE_DIR}/ace/Stack_Trace.h)
|
||||
set(HAVE_ACE_STACK_TRACE_H 1)
|
||||
set(HAVE_ACE_STACK_TRACE_H 1)
|
||||
else(EXISTS ${ACE_INCLUDE_DIR}/ace/Stack_Trace.h)
|
||||
message(STATUS "** Your libace is out of date. Please update your libace!")
|
||||
message(STATUS "** Your libace is out of date. Please update your libace!")
|
||||
endif(EXISTS ${ACE_INCLUDE_DIR}/ace/Stack_Trace.h)
|
||||
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config.h)
|
||||
@@ -201,8 +203,10 @@ set(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE)
|
||||
set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib")
|
||||
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
|
||||
|
||||
add_subdirectory(externals)
|
||||
add_subdirectory(src)
|
||||
|
||||
if(DO_SQL)
|
||||
message("* Copy SQL files ON")
|
||||
add_subdirectory(sql)
|
||||
message("* Copy SQL files ON")
|
||||
add_subdirectory(sql)
|
||||
endif(DO_SQL)
|
||||
|
||||
7
externals/CMakeLists.txt
vendored
Normal file
7
externals/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
add_subdirectory(ace)
|
||||
#add_subdirectory(bzip2)
|
||||
add_subdirectory(g3dlite)
|
||||
add_subdirectory(jemalloc)
|
||||
#add_subdirectory(libmpq)
|
||||
add_subdirectory(sockets)
|
||||
add_subdirectory(zlib)
|
||||
17
externals/PackageList.txt
vendored
17
externals/PackageList.txt
vendored
@@ -2,39 +2,52 @@ TrinityCore uses (parts of or in whole) the following opensource software :
|
||||
|
||||
ACE (ADAPTIVE Communication Environment)
|
||||
http://www.cs.wustl.edu/~schmidt/ACE.html
|
||||
Version: UNKNOWN
|
||||
|
||||
bzip2 (a freely available, patent free, high-quality data compressor)
|
||||
http://www.bzip.org/
|
||||
Version: 1.0.5
|
||||
|
||||
G3D 6.09 (a commercial-grade C++ 3D engine available as Open Source (BSD License)
|
||||
G3D (a commercial-grade C++ 3D engine available as Open Source (BSD License)
|
||||
http://g3d.sourceforge.net/
|
||||
Version: 6.09
|
||||
|
||||
jemalloc (a general-purpose scalable concurrent malloc-implementation)
|
||||
http://www.canonware.com/jemalloc/
|
||||
|
||||
Version: UNKNOWN
|
||||
|
||||
libMPQ (a library for reading MPQ files)
|
||||
https://libmpq.org/
|
||||
Version: 1.0.4
|
||||
|
||||
MersenneTwister (a very fast random number generator)
|
||||
http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html
|
||||
Version: 0.4.2
|
||||
|
||||
SFMT (SIMD-oriented Fast Mersenne Twister)
|
||||
http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/index.html
|
||||
Version: 1.3.3
|
||||
|
||||
MySQL (the world's most popular open source database software)
|
||||
http://www.mysql.com/about/
|
||||
Version: UNKNOWN
|
||||
|
||||
OpenSSL (an opensource toolkit implementing SSL v2/v3 and TLS v1 protocols)
|
||||
http://www.openssl.org/
|
||||
Version: UNKNOWN
|
||||
|
||||
sockets (a GPL licensed C++ class library wrapping the berkeley sockets C API)
|
||||
http://www.alhem.net/Sockets/
|
||||
Version: UNKNOWN
|
||||
|
||||
utf8-cpp (UTF-8 with C++ in a Portable Way)
|
||||
http://utfcpp.sourceforge.net/
|
||||
Version: 2.3
|
||||
|
||||
vld (a free open-source memory leak detection system for Visual C++)
|
||||
http://sites.google.com/site/dmoulding/vld
|
||||
Version: 1.0
|
||||
|
||||
zlib (A Massively Spiffy Yet Delicately Unobtrusive Compression Library)
|
||||
http://www.zlib.net/
|
||||
Version: 1.2.5
|
||||
|
||||
319
externals/bzip2/CHANGES
vendored
319
externals/bzip2/CHANGES
vendored
@@ -1,319 +0,0 @@
|
||||
------------------------------------------------------------------
|
||||
This file is part of bzip2/libbzip2, a program and library for
|
||||
lossless, block-sorting data compression.
|
||||
|
||||
bzip2/libbzip2 version 1.0.5 of 10 December 2007
|
||||
Copyright (C) 1996-2007 Julian Seward <jseward@bzip.org>
|
||||
|
||||
Please read the WARNING, DISCLAIMER and PATENTS sections in the
|
||||
README file.
|
||||
|
||||
This program is released under the terms of the license contained
|
||||
in the file LICENSE.
|
||||
------------------------------------------------------------------
|
||||
|
||||
|
||||
0.9.0
|
||||
~~~~~
|
||||
First version.
|
||||
|
||||
|
||||
0.9.0a
|
||||
~~~~~~
|
||||
Removed 'ranlib' from Makefile, since most modern Unix-es
|
||||
don't need it, or even know about it.
|
||||
|
||||
|
||||
0.9.0b
|
||||
~~~~~~
|
||||
Fixed a problem with error reporting in bzip2.c. This does not effect
|
||||
the library in any way. Problem is: versions 0.9.0 and 0.9.0a (of the
|
||||
program proper) compress and decompress correctly, but give misleading
|
||||
error messages (internal panics) when an I/O error occurs, instead of
|
||||
reporting the problem correctly. This shouldn't give any data loss
|
||||
(as far as I can see), but is confusing.
|
||||
|
||||
Made the inline declarations disappear for non-GCC compilers.
|
||||
|
||||
|
||||
0.9.0c
|
||||
~~~~~~
|
||||
Fixed some problems in the library pertaining to some boundary cases.
|
||||
This makes the library behave more correctly in those situations. The
|
||||
fixes apply only to features (calls and parameters) not used by
|
||||
bzip2.c, so the non-fixedness of them in previous versions has no
|
||||
effect on reliability of bzip2.c.
|
||||
|
||||
In bzlib.c:
|
||||
* made zero-length BZ_FLUSH work correctly in bzCompress().
|
||||
* fixed bzWrite/bzRead to ignore zero-length requests.
|
||||
* fixed bzread to correctly handle read requests after EOF.
|
||||
* wrong parameter order in call to bzDecompressInit in
|
||||
bzBuffToBuffDecompress. Fixed.
|
||||
|
||||
In compress.c:
|
||||
* changed setting of nGroups in sendMTFValues() so as to
|
||||
do a bit better on small files. This _does_ effect
|
||||
bzip2.c.
|
||||
|
||||
|
||||
0.9.5a
|
||||
~~~~~~
|
||||
Major change: add a fallback sorting algorithm (blocksort.c)
|
||||
to give reasonable behaviour even for very repetitive inputs.
|
||||
Nuked --repetitive-best and --repetitive-fast since they are
|
||||
no longer useful.
|
||||
|
||||
Minor changes: mostly a whole bunch of small changes/
|
||||
bugfixes in the driver (bzip2.c). Changes pertaining to the
|
||||
user interface are:
|
||||
|
||||
allow decompression of symlink'd files to stdout
|
||||
decompress/test files even without .bz2 extension
|
||||
give more accurate error messages for I/O errors
|
||||
when compressing/decompressing to stdout, don't catch control-C
|
||||
read flags from BZIP2 and BZIP environment variables
|
||||
decline to break hard links to a file unless forced with -f
|
||||
allow -c flag even with no filenames
|
||||
preserve file ownerships as far as possible
|
||||
make -s -1 give the expected block size (100k)
|
||||
add a flag -q --quiet to suppress nonessential warnings
|
||||
stop decoding flags after --, so files beginning in - can be handled
|
||||
resolved inconsistent naming: bzcat or bz2cat ?
|
||||
bzip2 --help now returns 0
|
||||
|
||||
Programming-level changes are:
|
||||
|
||||
fixed syntax error in GET_LL4 for Borland C++ 5.02
|
||||
let bzBuffToBuffDecompress return BZ_DATA_ERROR{_MAGIC}
|
||||
fix overshoot of mode-string end in bzopen_or_bzdopen
|
||||
wrapped bzlib.h in #ifdef __cplusplus ... extern "C" { ... }
|
||||
close file handles under all error conditions
|
||||
added minor mods so it compiles with DJGPP out of the box
|
||||
fixed Makefile so it doesn't give problems with BSD make
|
||||
fix uninitialised memory reads in dlltest.c
|
||||
|
||||
0.9.5b
|
||||
~~~~~~
|
||||
Open stdin/stdout in binary mode for DJGPP.
|
||||
|
||||
0.9.5c
|
||||
~~~~~~
|
||||
Changed BZ_N_OVERSHOOT to be ... + 2 instead of ... + 1. The + 1
|
||||
version could cause the sorted order to be wrong in some extremely
|
||||
obscure cases. Also changed setting of quadrant in blocksort.c.
|
||||
|
||||
0.9.5d
|
||||
~~~~~~
|
||||
The only functional change is to make bzlibVersion() in the library
|
||||
return the correct string. This has no effect whatsoever on the
|
||||
functioning of the bzip2 program or library. Added a couple of casts
|
||||
so the library compiles without warnings at level 3 in MS Visual
|
||||
Studio 6.0. Included a Y2K statement in the file Y2K_INFO. All other
|
||||
changes are minor documentation changes.
|
||||
|
||||
1.0
|
||||
~~~
|
||||
Several minor bugfixes and enhancements:
|
||||
|
||||
* Large file support. The library uses 64-bit counters to
|
||||
count the volume of data passing through it. bzip2.c
|
||||
is now compiled with -D_FILE_OFFSET_BITS=64 to get large
|
||||
file support from the C library. -v correctly prints out
|
||||
file sizes greater than 4 gigabytes. All these changes have
|
||||
been made without assuming a 64-bit platform or a C compiler
|
||||
which supports 64-bit ints, so, except for the C library
|
||||
aspect, they are fully portable.
|
||||
|
||||
* Decompression robustness. The library/program should be
|
||||
robust to any corruption of compressed data, detecting and
|
||||
handling _all_ corruption, instead of merely relying on
|
||||
the CRCs. What this means is that the program should
|
||||
never crash, given corrupted data, and the library should
|
||||
always return BZ_DATA_ERROR.
|
||||
|
||||
* Fixed an obscure race-condition bug only ever observed on
|
||||
Solaris, in which, if you were very unlucky and issued
|
||||
control-C at exactly the wrong time, both input and output
|
||||
files would be deleted.
|
||||
|
||||
* Don't run out of file handles on test/decompression when
|
||||
large numbers of files have invalid magic numbers.
|
||||
|
||||
* Avoid library namespace pollution. Prefix all exported
|
||||
symbols with BZ2_.
|
||||
|
||||
* Minor sorting enhancements from my DCC2000 paper.
|
||||
|
||||
* Advance the version number to 1.0, so as to counteract the
|
||||
(false-in-this-case) impression some people have that programs
|
||||
with version numbers less than 1.0 are in some way, experimental,
|
||||
pre-release versions.
|
||||
|
||||
* Create an initial Makefile-libbz2_so to build a shared library.
|
||||
Yes, I know I should really use libtool et al ...
|
||||
|
||||
* Make the program exit with 2 instead of 0 when decompression
|
||||
fails due to a bad magic number (ie, an invalid bzip2 header).
|
||||
Also exit with 1 (as the manual claims :-) whenever a diagnostic
|
||||
message would have been printed AND the corresponding operation
|
||||
is aborted, for example
|
||||
bzip2: Output file xx already exists.
|
||||
When a diagnostic message is printed but the operation is not
|
||||
aborted, for example
|
||||
bzip2: Can't guess original name for wurble -- using wurble.out
|
||||
then the exit value 0 is returned, unless some other problem is
|
||||
also detected.
|
||||
|
||||
I think it corresponds more closely to what the manual claims now.
|
||||
|
||||
|
||||
1.0.1
|
||||
~~~~~
|
||||
* Modified dlltest.c so it uses the new BZ2_ naming scheme.
|
||||
* Modified makefile-msc to fix minor build probs on Win2k.
|
||||
* Updated README.COMPILATION.PROBLEMS.
|
||||
|
||||
There are no functionality changes or bug fixes relative to version
|
||||
1.0.0. This is just a documentation update + a fix for minor Win32
|
||||
build problems. For almost everyone, upgrading from 1.0.0 to 1.0.1 is
|
||||
utterly pointless. Don't bother.
|
||||
|
||||
|
||||
1.0.2
|
||||
~~~~~
|
||||
A bug fix release, addressing various minor issues which have appeared
|
||||
in the 18 or so months since 1.0.1 was released. Most of the fixes
|
||||
are to do with file-handling or documentation bugs. To the best of my
|
||||
knowledge, there have been no data-loss-causing bugs reported in the
|
||||
compression/decompression engine of 1.0.0 or 1.0.1.
|
||||
|
||||
Note that this release does not improve the rather crude build system
|
||||
for Unix platforms. The general plan here is to autoconfiscate/
|
||||
libtoolise 1.0.2 soon after release, and release the result as 1.1.0
|
||||
or perhaps 1.2.0. That, however, is still just a plan at this point.
|
||||
|
||||
Here are the changes in 1.0.2. Bug-reporters and/or patch-senders in
|
||||
parentheses.
|
||||
|
||||
* Fix an infinite segfault loop in 1.0.1 when a directory is
|
||||
encountered in -f (force) mode.
|
||||
(Trond Eivind Glomsrod, Nicholas Nethercote, Volker Schmidt)
|
||||
|
||||
* Avoid double fclose() of output file on certain I/O error paths.
|
||||
(Solar Designer)
|
||||
|
||||
* Don't fail with internal error 1007 when fed a long stream (> 48MB)
|
||||
of byte 251. Also print useful message suggesting that 1007s may be
|
||||
caused by bad memory.
|
||||
(noticed by Juan Pedro Vallejo, fixed by me)
|
||||
|
||||
* Fix uninitialised variable silly bug in demo prog dlltest.c.
|
||||
(Jorj Bauer)
|
||||
|
||||
* Remove 512-MB limitation on recovered file size for bzip2recover
|
||||
on selected platforms which support 64-bit ints. At the moment
|
||||
all GCC supported platforms, and Win32.
|
||||
(me, Alson van der Meulen)
|
||||
|
||||
* Hard-code header byte values, to give correct operation on platforms
|
||||
using EBCDIC as their native character set (IBM's OS/390).
|
||||
(Leland Lucius)
|
||||
|
||||
* Copy file access times correctly.
|
||||
(Marty Leisner)
|
||||
|
||||
* Add distclean and check targets to Makefile.
|
||||
(Michael Carmack)
|
||||
|
||||
* Parameterise use of ar and ranlib in Makefile. Also add $(LDFLAGS).
|
||||
(Rich Ireland, Bo Thorsen)
|
||||
|
||||
* Pass -p (create parent dirs as needed) to mkdir during make install.
|
||||
(Jeremy Fusco)
|
||||
|
||||
* Dereference symlinks when copying file permissions in -f mode.
|
||||
(Volker Schmidt)
|
||||
|
||||
* Majorly simplify implementation of uInt64_qrm10.
|
||||
(Bo Lindbergh)
|
||||
|
||||
* Check the input file still exists before deleting the output one,
|
||||
when aborting in cleanUpAndFail().
|
||||
(Joerg Prante, Robert Linden, Matthias Krings)
|
||||
|
||||
Also a bunch of patches courtesy of Philippe Troin, the Debian maintainer
|
||||
of bzip2:
|
||||
|
||||
* Wrapper scripts (with manpages): bzdiff, bzgrep, bzmore.
|
||||
|
||||
* Spelling changes and minor enhancements in bzip2.1.
|
||||
|
||||
* Avoid race condition between creating the output file and setting its
|
||||
interim permissions safely, by using fopen_output_safely().
|
||||
No changes to bzip2recover since there is no issue with file
|
||||
permissions there.
|
||||
|
||||
* do not print senseless report with -v when compressing an empty
|
||||
file.
|
||||
|
||||
* bzcat -f works on non-bzip2 files.
|
||||
|
||||
* do not try to escape shell meta-characters on unix (the shell takes
|
||||
care of these).
|
||||
|
||||
* added --fast and --best aliases for -1 -9 for gzip compatibility.
|
||||
|
||||
|
||||
1.0.3 (15 Feb 05)
|
||||
~~~~~~~~~~~~~~~~~
|
||||
Fixes some minor bugs since the last version, 1.0.2.
|
||||
|
||||
* Further robustification against corrupted compressed data.
|
||||
There are currently no known bitstreams which can cause the
|
||||
decompressor to crash, loop or access memory which does not
|
||||
belong to it. If you are using bzip2 or the library to
|
||||
decompress bitstreams from untrusted sources, an upgrade
|
||||
to 1.0.3 is recommended. This fixes CAN-2005-1260.
|
||||
|
||||
* The documentation has been converted to XML, from which html
|
||||
and pdf can be derived.
|
||||
|
||||
* Various minor bugs in the documentation have been fixed.
|
||||
|
||||
* Fixes for various compilation warnings with newer versions of
|
||||
gcc, and on 64-bit platforms.
|
||||
|
||||
* The BZ_NO_STDIO cpp symbol was not properly observed in 1.0.2.
|
||||
This has been fixed.
|
||||
|
||||
|
||||
1.0.4 (20 Dec 06)
|
||||
~~~~~~~~~~~~~~~~~
|
||||
Fixes some minor bugs since the last version, 1.0.3.
|
||||
|
||||
* Fix file permissions race problem (CAN-2005-0953).
|
||||
|
||||
* Avoid possible segfault in BZ2_bzclose. From Coverity's NetBSD
|
||||
scan.
|
||||
|
||||
* 'const'/prototype cleanups in the C code.
|
||||
|
||||
* Change default install location to /usr/local, and handle multiple
|
||||
'make install's without error.
|
||||
|
||||
* Sanitise file names more carefully in bzgrep. Fixes CAN-2005-0758
|
||||
to the extent that applies to bzgrep.
|
||||
|
||||
* Use 'mktemp' rather than 'tempfile' in bzdiff.
|
||||
|
||||
* Tighten up a couple of assertions in blocksort.c following automated
|
||||
analysis.
|
||||
|
||||
* Fix minor doc/comment bugs.
|
||||
|
||||
|
||||
1.0.5 (10 Dec 07)
|
||||
~~~~~~~~~~~~~~~~~
|
||||
Security fix only. Fixes CERT-FI 20469 as it applies to bzip2.
|
||||
|
||||
10
externals/bzip2/CMakeLists.txt
vendored
Normal file
10
externals/bzip2/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
file(GLOB sources *.cpp)
|
||||
set(bzip2_STAT_SRCS
|
||||
${sources}
|
||||
)
|
||||
|
||||
include_directories(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
)
|
||||
|
||||
add_library(bzip2 STATIC ${bzip2_STAT_SRCS})
|
||||
42
externals/bzip2/LICENSE
vendored
42
externals/bzip2/LICENSE
vendored
@@ -1,42 +0,0 @@
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
This program, "bzip2", the associated library "libbzip2", and all
|
||||
documentation, are copyright (C) 1996-2007 Julian R Seward. All
|
||||
rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. The origin of this software must not be misrepresented; you must
|
||||
not claim that you wrote the original software. If you use this
|
||||
software in a product, an acknowledgment in the product
|
||||
documentation would be appreciated but is not required.
|
||||
|
||||
3. Altered source versions must be plainly marked as such, and must
|
||||
not be misrepresented as being the original software.
|
||||
|
||||
4. The name of the author may not be used to endorse or promote
|
||||
products derived from this software without specific prior written
|
||||
permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
||||
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Julian Seward, jseward@bzip.org
|
||||
bzip2/libbzip2 version 1.0.5 of 10 December 2007
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
366
externals/g3dlite/AABox.cpp
vendored
Normal file
366
externals/g3dlite/AABox.cpp
vendored
Normal file
@@ -0,0 +1,366 @@
|
||||
/**
|
||||
@file AABox.cpp
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
@created 2004-01-10
|
||||
@edited 2006-01-11
|
||||
*/
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/AABox.h"
|
||||
#include "G3D/Box.h"
|
||||
#include "G3D/Plane.h"
|
||||
#include "G3D/Sphere.h"
|
||||
#include "G3D/BinaryInput.h"
|
||||
#include "G3D/BinaryOutput.h"
|
||||
|
||||
|
||||
namespace G3D {
|
||||
|
||||
const AABox& AABox::maxFinite() {
|
||||
static const AABox b = AABox(Vector3::minFinite(),
|
||||
Vector3::maxFinite());
|
||||
return b;
|
||||
}
|
||||
|
||||
|
||||
const AABox& AABox::large() {
|
||||
static const AABox b = AABox(Vector3::minFinite() * 0.5f,
|
||||
Vector3::maxFinite() * 0.5f);
|
||||
return b;
|
||||
}
|
||||
|
||||
|
||||
const AABox& AABox::inf() {
|
||||
static const AABox b = AABox(-Vector3::inf(), Vector3::inf());
|
||||
return b;
|
||||
}
|
||||
|
||||
|
||||
const AABox& AABox::zero() {
|
||||
static const AABox b = AABox(Vector3::zero(), Vector3::zero());
|
||||
return b;
|
||||
}
|
||||
|
||||
|
||||
void AABox::serialize(class BinaryOutput& b) const {
|
||||
b.writeVector3(lo);
|
||||
b.writeVector3(hi);
|
||||
}
|
||||
|
||||
|
||||
void AABox::deserialize(class BinaryInput& b) {
|
||||
lo = b.readVector3();
|
||||
hi = b.readVector3();
|
||||
}
|
||||
|
||||
|
||||
void AABox::split(const Vector3::Axis& axis, float location, AABox& low, AABox& high) const {
|
||||
// Low, medium, and high along the chosen axis
|
||||
float L = G3D::min(location, lo[axis]);
|
||||
float M = G3D::min(G3D::max(location, lo[axis]), hi[axis]);
|
||||
float H = G3D::max(location, hi[axis]);
|
||||
|
||||
// Copy over this box.
|
||||
high = low = *this;
|
||||
|
||||
// Now move the split points along the special axis
|
||||
low.lo[axis] = L;
|
||||
low.hi[axis] = M;
|
||||
high.lo[axis] = M;
|
||||
high.hi[axis] = H;
|
||||
}
|
||||
|
||||
|
||||
Vector3 AABox::randomSurfacePoint() const {
|
||||
Vector3 extent = hi - lo;
|
||||
float aXY = extent.x * extent.y;
|
||||
float aYZ = extent.y * extent.z;
|
||||
float aZX = extent.z * extent.x;
|
||||
|
||||
float r = (float)uniformRandom(0.0f, aXY + aYZ + aZX);
|
||||
|
||||
// Choose evenly between positive and negative face planes
|
||||
float d = ((float)uniformRandom(0, 1) < 0.5f) ? 0.0f : 1.0f;
|
||||
|
||||
// The probability of choosing a given face is proportional to
|
||||
// its area.
|
||||
if (r < aXY) {
|
||||
return
|
||||
lo +
|
||||
Vector3(
|
||||
(float)uniformRandom(0.0f, extent.x),
|
||||
(float)uniformRandom(0.0f, extent.y),
|
||||
d * extent.z);
|
||||
} else if (r < aYZ) {
|
||||
return
|
||||
lo +
|
||||
Vector3(
|
||||
d * extent.x,
|
||||
(float)uniformRandom(0, extent.y),
|
||||
(float)uniformRandom(0, extent.z));
|
||||
} else {
|
||||
return
|
||||
lo +
|
||||
Vector3(
|
||||
(float)uniformRandom(0, extent.x),
|
||||
d * extent.y,
|
||||
(float)uniformRandom(0, extent.z));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Vector3 AABox::randomInteriorPoint() const {
|
||||
return Vector3(
|
||||
(float)uniformRandom(lo.x, hi.x),
|
||||
(float)uniformRandom(lo.y, hi.y),
|
||||
(float)uniformRandom(lo.z, hi.z));
|
||||
}
|
||||
|
||||
|
||||
bool AABox::intersects(const AABox& other) const {
|
||||
// Must be overlap along all three axes.
|
||||
// Try to find a separating axis.
|
||||
|
||||
for (int a = 0; a < 3; ++a) {
|
||||
|
||||
// |--------|
|
||||
// |------|
|
||||
|
||||
if ((lo[a] > other.hi[a]) ||
|
||||
(hi[a] < other.lo[a])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int AABox::dummy = 0;
|
||||
|
||||
bool AABox::culledBy(
|
||||
const Array<Plane>& plane,
|
||||
int& cullingPlane,
|
||||
const uint32 _inMask,
|
||||
uint32& childMask) const {
|
||||
|
||||
uint32 inMask = _inMask;
|
||||
assert(plane.size() < 31);
|
||||
|
||||
childMask = 0;
|
||||
|
||||
const bool finite =
|
||||
(abs(lo.x) < G3D::finf()) &&
|
||||
(abs(hi.x) < G3D::finf()) &&
|
||||
(abs(lo.y) < G3D::finf()) &&
|
||||
(abs(hi.y) < G3D::finf()) &&
|
||||
(abs(lo.z) < G3D::finf()) &&
|
||||
(abs(hi.z) < G3D::finf());
|
||||
|
||||
// See if there is one plane for which all of the
|
||||
// vertices are in the negative half space.
|
||||
for (int p = 0; p < plane.size(); ++p) {
|
||||
|
||||
// Only test planes that are not masked
|
||||
if ((inMask & 1) != 0) {
|
||||
|
||||
Vector3 corner;
|
||||
|
||||
int numContained = 0;
|
||||
int v = 0;
|
||||
|
||||
// We can early-out only if we have found one point on each
|
||||
// side of the plane (i.e. if we are straddling). That
|
||||
// occurs when (numContained < v) && (numContained > 0)
|
||||
for (v = 0; (v < 8) && ((numContained == v) || (numContained == 0)); ++v) {
|
||||
// Unrolling these 3 if's into a switch decreases performance
|
||||
// by about 2x
|
||||
corner.x = (v & 1) ? hi.x : lo.x;
|
||||
corner.y = (v & 2) ? hi.y : lo.y;
|
||||
corner.z = (v & 4) ? hi.z : lo.z;
|
||||
|
||||
if (finite) { // this branch is highly predictable
|
||||
if (plane[p].halfSpaceContainsFinite(corner)) {
|
||||
++numContained;
|
||||
}
|
||||
} else {
|
||||
if (plane[p].halfSpaceContains(corner)) {
|
||||
++numContained;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (numContained == 0) {
|
||||
// Plane p culled the box
|
||||
cullingPlane = p;
|
||||
|
||||
// The caller should not recurse into the children,
|
||||
// since the parent is culled. If they do recurse,
|
||||
// make them only test against this one plane, which
|
||||
// will immediately cull the volume.
|
||||
childMask = 1 << p;
|
||||
return true;
|
||||
|
||||
} else if (numContained < v) {
|
||||
// The bounding volume straddled the plane; we have
|
||||
// to keep testing against this plane
|
||||
childMask |= (1 << p);
|
||||
}
|
||||
}
|
||||
|
||||
// Move on to the next bit.
|
||||
inMask = inMask >> 1;
|
||||
}
|
||||
|
||||
// None of the planes could cull this box
|
||||
cullingPlane = -1;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool AABox::culledBy(
|
||||
const Array<Plane>& plane,
|
||||
int& cullingPlane,
|
||||
const uint32 _inMask) const {
|
||||
|
||||
uint32 inMask = _inMask;
|
||||
assert(plane.size() < 31);
|
||||
|
||||
const bool finite =
|
||||
(abs(lo.x) < G3D::finf()) &&
|
||||
(abs(hi.x) < G3D::finf()) &&
|
||||
(abs(lo.y) < G3D::finf()) &&
|
||||
(abs(hi.y) < G3D::finf()) &&
|
||||
(abs(lo.z) < G3D::finf()) &&
|
||||
(abs(hi.z) < G3D::finf());
|
||||
|
||||
// See if there is one plane for which all of the
|
||||
// vertices are in the negative half space.
|
||||
for (int p = 0; p < plane.size(); ++p) {
|
||||
|
||||
// Only test planes that are not masked
|
||||
if ((inMask & 1) != 0) {
|
||||
|
||||
bool culled = true;
|
||||
Vector3 corner;
|
||||
|
||||
int v;
|
||||
|
||||
// Assume this plane culls all points. See if there is a point
|
||||
// not culled by the plane... early out when at least one point
|
||||
// is in the positive half space.
|
||||
for (v = 0; (v < 8) && culled; ++v) {
|
||||
|
||||
// Unrolling these 3 if's into a switch decreases performance
|
||||
// by about 2x
|
||||
corner.x = (v & 1) ? hi.x : lo.x;
|
||||
corner.y = (v & 2) ? hi.y : lo.y;
|
||||
corner.z = (v & 4) ? hi.z : lo.z;
|
||||
|
||||
if (finite) { // this branch is highly predictable
|
||||
culled = ! plane[p].halfSpaceContainsFinite(corner);
|
||||
} else {
|
||||
culled = ! plane[p].halfSpaceContains(corner);
|
||||
}
|
||||
}
|
||||
|
||||
if (culled) {
|
||||
// Plane p culled the box
|
||||
cullingPlane = p;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Move on to the next bit.
|
||||
inMask = inMask >> 1;
|
||||
}
|
||||
|
||||
// None of the planes could cull this box
|
||||
cullingPlane = -1;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool AABox::intersects(const class Sphere& sphere) const {
|
||||
double d = 0;
|
||||
|
||||
//find the square of the distance
|
||||
//from the sphere to the box
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
if (sphere.center[i] < lo[i]) {
|
||||
d += square(sphere.center[i] - lo[i]);
|
||||
} else if (sphere.center[i] > hi[i]) {
|
||||
d += square(sphere.center[i] - hi[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return d <= square(sphere.radius);
|
||||
}
|
||||
|
||||
Vector3 AABox::corner(int index) const {
|
||||
|
||||
// default constructor inits all components to 0
|
||||
Vector3 v;
|
||||
|
||||
switch (index)
|
||||
{
|
||||
case 0:
|
||||
v.x = lo.x;
|
||||
v.y = lo.y;
|
||||
v.z = hi.z;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
v.x = hi.x;
|
||||
v.y = lo.y;
|
||||
v.z = hi.z;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
v.x = hi.x;
|
||||
v.y = hi.y;
|
||||
v.z = hi.z;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
v.x = lo.x;
|
||||
v.y = hi.y;
|
||||
v.z = hi.z;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
v.x = lo.x;
|
||||
v.y = lo.y;
|
||||
v.z = lo.z;
|
||||
break;
|
||||
|
||||
case 5:
|
||||
v.x = hi.x;
|
||||
v.y = lo.y;
|
||||
v.z = lo.z;
|
||||
break;
|
||||
|
||||
case 6:
|
||||
v.x = hi.x;
|
||||
v.y = hi.y;
|
||||
v.z = lo.z;
|
||||
break;
|
||||
|
||||
case 7:
|
||||
v.x = lo.x;
|
||||
v.y = hi.y;
|
||||
v.z = lo.z;
|
||||
break;
|
||||
|
||||
default:
|
||||
debugAssertM(false, "Invalid corner index");
|
||||
break;
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
1237
externals/g3dlite/Any.cpp
vendored
Normal file
1237
externals/g3dlite/Any.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
81
externals/g3dlite/BinaryFormat.cpp
vendored
Normal file
81
externals/g3dlite/BinaryFormat.cpp
vendored
Normal file
@@ -0,0 +1,81 @@
|
||||
/**
|
||||
@file BinaryFormat.cpp
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
@created 2005-06-10
|
||||
@edited 2005-06-10
|
||||
*/
|
||||
|
||||
#include "G3D/BinaryFormat.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
int32 byteSize(BinaryFormat f) {
|
||||
switch (f) {
|
||||
case BOOL8_BINFMT:
|
||||
case UINT8_BINFMT:
|
||||
case INT8_BINFMT:
|
||||
return 1;
|
||||
|
||||
case UINT16_BINFMT:
|
||||
case INT16_BINFMT:
|
||||
return 2;
|
||||
|
||||
case FLOAT16_BINFMT:
|
||||
return 2;
|
||||
|
||||
case UINT32_BINFMT:
|
||||
case INT32_BINFMT:
|
||||
case FLOAT32_BINFMT:
|
||||
return 4;
|
||||
|
||||
case FLOAT64_BINFMT:
|
||||
case UINT64_BINFMT:
|
||||
case INT64_BINFMT:
|
||||
return 8;
|
||||
|
||||
case INT128_BINFMT:
|
||||
case UINT128_BINFMT:
|
||||
return 16;
|
||||
|
||||
case VECTOR2_BINFMT:
|
||||
return 2 * 4;
|
||||
|
||||
case VECTOR2INT16_BINFMT:
|
||||
return 2 * 2;
|
||||
|
||||
case VECTOR3_BINFMT:
|
||||
return 3 * 4;
|
||||
|
||||
case VECTOR3INT16_BINFMT:
|
||||
return 3 * 2;
|
||||
|
||||
case VECTOR4_BINFMT:
|
||||
return 4 * 4;
|
||||
|
||||
case VECTOR4INT16_BINFMT:
|
||||
return 4 * 4;
|
||||
|
||||
case COLOR3_BINFMT:
|
||||
return 3 * 4;
|
||||
|
||||
case COLOR3UINT8_BINFMT:
|
||||
return 3 * 1;
|
||||
|
||||
case COLOR3INT16_BINFMT:
|
||||
return 3 * 2;
|
||||
|
||||
case COLOR4_BINFMT:
|
||||
return 4 * 4;
|
||||
|
||||
case COLOR4UINT8_BINFMT:
|
||||
return 4 * 1;
|
||||
|
||||
case COLOR4INT16_BINFMT:
|
||||
return 4 * 2;
|
||||
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
568
externals/g3dlite/BinaryInput.cpp
vendored
Normal file
568
externals/g3dlite/BinaryInput.cpp
vendored
Normal file
@@ -0,0 +1,568 @@
|
||||
/**
|
||||
@file BinaryInput.cpp
|
||||
|
||||
@author Morgan McGuire, graphics3d.com
|
||||
Copyright 2001-2007, Morgan McGuire. All rights reserved.
|
||||
|
||||
@created 2001-08-09
|
||||
@edited 2005-02-24
|
||||
|
||||
|
||||
<PRE>
|
||||
{
|
||||
BinaryOutput b("c:/tmp/test.b", BinaryOutput::LITTLE_ENDIAN);
|
||||
|
||||
float f = 3.1415926;
|
||||
int i = 1027221;
|
||||
std::string s = "Hello World!";
|
||||
|
||||
b.writeFloat32(f);
|
||||
b.writeInt32(i);
|
||||
b.writeString(s);
|
||||
b.commit();
|
||||
|
||||
|
||||
BinaryInput in("c:/tmp/test.b", BinaryInput::LITTLE_ENDIAN);
|
||||
|
||||
debugAssert(f == in.readFloat32());
|
||||
int ii = in.readInt32();
|
||||
debugAssert(i == ii);
|
||||
debugAssert(s == in.readString());
|
||||
}
|
||||
</PRE>
|
||||
*/
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/BinaryInput.h"
|
||||
#include "G3D/Array.h"
|
||||
#include "G3D/fileutils.h"
|
||||
#include "G3D/Log.h"
|
||||
#include <zlib.h>
|
||||
|
||||
#include <cstring>
|
||||
|
||||
namespace G3D {
|
||||
|
||||
void BinaryInput::readBool8(std::vector<bool>& out, int64 n) {
|
||||
out.resize((int)n);
|
||||
// std::vector optimizes bool in a way that prevents fast reading
|
||||
for (int64 i = 0; i < n ; ++i) {
|
||||
out[i] = readBool8();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void BinaryInput::readBool8(Array<bool>& out, int64 n) {
|
||||
out.resize(n);
|
||||
readBool8(out.begin(), n);
|
||||
}
|
||||
|
||||
|
||||
#define IMPLEMENT_READER(ucase, lcase)\
|
||||
void BinaryInput::read##ucase(std::vector<lcase>& out, int64 n) {\
|
||||
out.resize(n);\
|
||||
read##ucase(&out[0], n);\
|
||||
}\
|
||||
\
|
||||
\
|
||||
void BinaryInput::read##ucase(Array<lcase>& out, int64 n) {\
|
||||
out.resize(n);\
|
||||
read##ucase(out.begin(), n);\
|
||||
}
|
||||
|
||||
|
||||
IMPLEMENT_READER(UInt8, uint8)
|
||||
IMPLEMENT_READER(Int8, int8)
|
||||
IMPLEMENT_READER(UInt16, uint16)
|
||||
IMPLEMENT_READER(Int16, int16)
|
||||
IMPLEMENT_READER(UInt32, uint32)
|
||||
IMPLEMENT_READER(Int32, int32)
|
||||
IMPLEMENT_READER(UInt64, uint64)
|
||||
IMPLEMENT_READER(Int64, int64)
|
||||
IMPLEMENT_READER(Float32, float32)
|
||||
IMPLEMENT_READER(Float64, float64)
|
||||
|
||||
#undef IMPLEMENT_READER
|
||||
|
||||
// Data structures that are one byte per element can be
|
||||
// directly copied, regardles of endian-ness.
|
||||
#define IMPLEMENT_READER(ucase, lcase)\
|
||||
void BinaryInput::read##ucase(lcase* out, int64 n) {\
|
||||
if (sizeof(lcase) == 1) {\
|
||||
readBytes(out, n);\
|
||||
} else {\
|
||||
for (int64 i = 0; i < n ; ++i) {\
|
||||
out[i] = read##ucase();\
|
||||
}\
|
||||
}\
|
||||
}
|
||||
|
||||
IMPLEMENT_READER(Bool8, bool)
|
||||
IMPLEMENT_READER(UInt8, uint8)
|
||||
IMPLEMENT_READER(Int8, int8)
|
||||
|
||||
#undef IMPLEMENT_READER
|
||||
|
||||
|
||||
#define IMPLEMENT_READER(ucase, lcase)\
|
||||
void BinaryInput::read##ucase(lcase* out, int64 n) {\
|
||||
if (m_swapBytes) {\
|
||||
for (int64 i = 0; i < n; ++i) {\
|
||||
out[i] = read##ucase();\
|
||||
}\
|
||||
} else {\
|
||||
readBytes(out, sizeof(lcase) * n);\
|
||||
}\
|
||||
}
|
||||
|
||||
|
||||
IMPLEMENT_READER(UInt16, uint16)
|
||||
IMPLEMENT_READER(Int16, int16)
|
||||
IMPLEMENT_READER(UInt32, uint32)
|
||||
IMPLEMENT_READER(Int32, int32)
|
||||
IMPLEMENT_READER(UInt64, uint64)
|
||||
IMPLEMENT_READER(Int64, int64)
|
||||
IMPLEMENT_READER(Float32, float32)
|
||||
IMPLEMENT_READER(Float64, float64)
|
||||
|
||||
#undef IMPLEMENT_READER
|
||||
|
||||
void BinaryInput::loadIntoMemory(int64 startPosition, int64 minLength) {
|
||||
// Load the next section of the file
|
||||
debugAssertM(m_filename != "<memory>", "Read past end of file.");
|
||||
|
||||
int64 absPos = m_alreadyRead + m_pos;
|
||||
|
||||
if (m_bufferLength < minLength) {
|
||||
// The current buffer isn't big enough to hold the chunk we want to read.
|
||||
// This happens if there was little memory available during the initial constructor
|
||||
// read but more memory has since been freed.
|
||||
m_bufferLength = minLength;
|
||||
debugAssert(m_freeBuffer);
|
||||
m_buffer = (uint8*)System::realloc(m_buffer, m_bufferLength);
|
||||
if (m_buffer == NULL) {
|
||||
throw "Tried to read a larger memory chunk than could fit in memory. (2)";
|
||||
}
|
||||
}
|
||||
|
||||
m_alreadyRead = startPosition;
|
||||
|
||||
# ifdef G3D_WIN32
|
||||
FILE* file = fopen(m_filename.c_str(), "rb");
|
||||
debugAssert(file);
|
||||
int ret = fseek(file, (off_t)m_alreadyRead, SEEK_SET);
|
||||
debugAssert(ret == 0);
|
||||
size_t toRead = (size_t)G3D::min(m_bufferLength, m_length - m_alreadyRead);
|
||||
ret = fread(m_buffer, 1, toRead, file);
|
||||
debugAssert(ret == toRead);
|
||||
fclose(file);
|
||||
file = NULL;
|
||||
|
||||
# else
|
||||
FILE* file = fopen(m_filename.c_str(), "rb");
|
||||
debugAssert(file);
|
||||
int ret = fseeko(file, (off_t)m_alreadyRead, SEEK_SET);
|
||||
debugAssert(ret == 0);
|
||||
size_t toRead = (size_t)G3D::min<int64>(m_bufferLength, m_length - m_alreadyRead);
|
||||
ret = fread(m_buffer, 1, toRead, file);
|
||||
debugAssert((size_t)ret == (size_t)toRead);
|
||||
fclose(file);
|
||||
file = NULL;
|
||||
# endif
|
||||
|
||||
m_pos = absPos - m_alreadyRead;
|
||||
debugAssert(m_pos >= 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
const bool BinaryInput::NO_COPY = false;
|
||||
|
||||
static bool needSwapBytes(G3DEndian fileEndian) {
|
||||
return (fileEndian != System::machineEndian());
|
||||
}
|
||||
|
||||
|
||||
/** Helper used by the constructors for decompression */
|
||||
static uint32 readUInt32(const uint8* data, bool swapBytes) {
|
||||
if (swapBytes) {
|
||||
uint8 out[4];
|
||||
out[0] = data[3];
|
||||
out[1] = data[2];
|
||||
out[2] = data[1];
|
||||
out[3] = data[0];
|
||||
return *((uint32*)out);
|
||||
} else {
|
||||
return *((uint32*)data);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void BinaryInput::setEndian(G3DEndian e) {
|
||||
m_fileEndian = e;
|
||||
m_swapBytes = needSwapBytes(m_fileEndian);
|
||||
}
|
||||
|
||||
|
||||
BinaryInput::BinaryInput(
|
||||
const uint8* data,
|
||||
int64 dataLen,
|
||||
G3DEndian dataEndian,
|
||||
bool compressed,
|
||||
bool copyMemory) :
|
||||
m_filename("<memory>"),
|
||||
m_bitPos(0),
|
||||
m_bitString(0),
|
||||
m_beginEndBits(0),
|
||||
m_alreadyRead(0),
|
||||
m_bufferLength(0),
|
||||
m_pos(0) {
|
||||
|
||||
m_freeBuffer = copyMemory || compressed;
|
||||
|
||||
setEndian(dataEndian);
|
||||
|
||||
if (compressed) {
|
||||
// Read the decompressed size from the first 4 bytes
|
||||
m_length = G3D::readUInt32(data, m_swapBytes);
|
||||
|
||||
debugAssert(m_freeBuffer);
|
||||
m_buffer = (uint8*)System::alignedMalloc(m_length, 16);
|
||||
|
||||
unsigned long L = m_length;
|
||||
// Decompress with zlib
|
||||
int64 result = uncompress(m_buffer, (unsigned long*)&L, data + 4, dataLen - 4);
|
||||
m_length = L;
|
||||
m_bufferLength = L;
|
||||
debugAssert(result == Z_OK); (void)result;
|
||||
|
||||
} else {
|
||||
m_length = dataLen;
|
||||
m_bufferLength = m_length;
|
||||
if (! copyMemory) {
|
||||
debugAssert(!m_freeBuffer);
|
||||
m_buffer = const_cast<uint8*>(data);
|
||||
} else {
|
||||
debugAssert(m_freeBuffer);
|
||||
m_buffer = (uint8*)System::alignedMalloc(m_length, 16);
|
||||
System::memcpy(m_buffer, data, dataLen);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
BinaryInput::BinaryInput(
|
||||
const std::string& filename,
|
||||
G3DEndian fileEndian,
|
||||
bool compressed) :
|
||||
m_filename(filename),
|
||||
m_bitPos(0),
|
||||
m_bitString(0),
|
||||
m_beginEndBits(0),
|
||||
m_alreadyRead(0),
|
||||
m_length(0),
|
||||
m_bufferLength(0),
|
||||
m_buffer(NULL),
|
||||
m_pos(0),
|
||||
m_freeBuffer(true) {
|
||||
|
||||
setEndian(fileEndian);
|
||||
|
||||
// Update global file tracker
|
||||
_internal::currentFilesUsed.insert(m_filename);
|
||||
|
||||
|
||||
if (! fileExists(m_filename, false)) {
|
||||
std::string zipfile;
|
||||
std::string internalfile;
|
||||
if (zipfileExists(m_filename, zipfile, internalfile)) {
|
||||
// Load from zipfile
|
||||
void* v;
|
||||
size_t s;
|
||||
zipRead(filename, v, s);
|
||||
m_buffer = reinterpret_cast<uint8*>(v);
|
||||
m_bufferLength = m_length = s;
|
||||
if (compressed) {
|
||||
decompress();
|
||||
}
|
||||
m_freeBuffer = true;
|
||||
} else {
|
||||
Log::common()->printf("Warning: File not found: %s\n", m_filename.c_str());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Figure out how big the file is and verify that it exists.
|
||||
m_length = fileLength(m_filename);
|
||||
|
||||
// Read the file into memory
|
||||
FILE* file = fopen(m_filename.c_str(), "rb");
|
||||
|
||||
if (! file || (m_length == -1)) {
|
||||
throw format("File not found: \"%s\"", m_filename.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
if (! compressed && (m_length > INITIAL_BUFFER_LENGTH)) {
|
||||
// Read only a subset of the file so we don't consume
|
||||
// all available memory.
|
||||
m_bufferLength = INITIAL_BUFFER_LENGTH;
|
||||
} else {
|
||||
// Either the length is fine or the file is compressed
|
||||
// and requires us to read the whole thing for zlib.
|
||||
m_bufferLength = m_length;
|
||||
}
|
||||
|
||||
debugAssert(m_freeBuffer);
|
||||
m_buffer = (uint8*)System::alignedMalloc(m_bufferLength, 16);
|
||||
if (m_buffer == NULL) {
|
||||
if (compressed) {
|
||||
throw "Not enough memory to load compressed file. (1)";
|
||||
}
|
||||
|
||||
// Try to allocate a small array; not much memory is available.
|
||||
// Give up if we can't allocate even 1k.
|
||||
while ((m_buffer == NULL) && (m_bufferLength > 1024)) {
|
||||
m_bufferLength /= 2;
|
||||
m_buffer = (uint8*)System::alignedMalloc(m_bufferLength, 16);
|
||||
}
|
||||
}
|
||||
debugAssert(m_buffer);
|
||||
|
||||
fread(m_buffer, m_bufferLength, sizeof(int8), file);
|
||||
fclose(file);
|
||||
file = NULL;
|
||||
|
||||
if (compressed) {
|
||||
if (m_bufferLength != m_length) {
|
||||
throw "Not enough memory to load compressed file. (2)";
|
||||
}
|
||||
|
||||
decompress();
|
||||
}
|
||||
}
|
||||
|
||||
void BinaryInput::decompress() {
|
||||
// Decompress
|
||||
// Use the existing buffer as the source, allocate
|
||||
// a new buffer to use as the destination.
|
||||
|
||||
int64 tempLength = m_length;
|
||||
m_length = G3D::readUInt32(m_buffer, m_swapBytes);
|
||||
|
||||
// The file couldn't have better than 500:1 compression
|
||||
alwaysAssertM(m_length < m_bufferLength * 500, "Compressed file header is corrupted");
|
||||
|
||||
uint8* tempBuffer = m_buffer;
|
||||
m_buffer = (uint8*)System::alignedMalloc(m_length, 16);
|
||||
|
||||
debugAssert(m_buffer);
|
||||
debugAssert(isValidHeapPointer(tempBuffer));
|
||||
debugAssert(isValidHeapPointer(m_buffer));
|
||||
|
||||
unsigned long L = m_length;
|
||||
int64 result = uncompress(m_buffer, &L, tempBuffer + 4, tempLength - 4);
|
||||
m_length = L;
|
||||
m_bufferLength = m_length;
|
||||
|
||||
debugAssertM(result == Z_OK, "BinaryInput/zlib detected corruption in " + m_filename);
|
||||
(void)result;
|
||||
|
||||
System::alignedFree(tempBuffer);
|
||||
}
|
||||
|
||||
|
||||
void BinaryInput::readBytes(void* bytes, int64 n) {
|
||||
prepareToRead(n);
|
||||
debugAssert(isValidPointer(bytes));
|
||||
|
||||
memcpy(bytes, m_buffer + m_pos, n);
|
||||
m_pos += n;
|
||||
}
|
||||
|
||||
|
||||
BinaryInput::~BinaryInput() {
|
||||
|
||||
if (m_freeBuffer) {
|
||||
System::alignedFree(m_buffer);
|
||||
}
|
||||
m_buffer = NULL;
|
||||
}
|
||||
|
||||
|
||||
uint64 BinaryInput::readUInt64() {
|
||||
prepareToRead(8);
|
||||
uint8 out[8];
|
||||
|
||||
if (m_swapBytes) {
|
||||
out[0] = m_buffer[m_pos + 7];
|
||||
out[1] = m_buffer[m_pos + 6];
|
||||
out[2] = m_buffer[m_pos + 5];
|
||||
out[3] = m_buffer[m_pos + 4];
|
||||
out[4] = m_buffer[m_pos + 3];
|
||||
out[5] = m_buffer[m_pos + 2];
|
||||
out[6] = m_buffer[m_pos + 1];
|
||||
out[7] = m_buffer[m_pos + 0];
|
||||
} else {
|
||||
*(uint64*)out = *(uint64*)(m_buffer + m_pos);
|
||||
}
|
||||
|
||||
m_pos += 8;
|
||||
return *(uint64*)out;
|
||||
}
|
||||
|
||||
|
||||
std::string BinaryInput::readString(int64 n) {
|
||||
prepareToRead(n);
|
||||
debugAssertM((m_pos + n) <= m_length, "Read past end of file");
|
||||
|
||||
char *s = (char*)System::alignedMalloc(n + 1, 16);
|
||||
assert(s != NULL);
|
||||
|
||||
memcpy(s, m_buffer + m_pos, n);
|
||||
// There may not be a null, so make sure
|
||||
// we add one.
|
||||
s[n] = '\0';
|
||||
|
||||
std::string out = s;
|
||||
System::alignedFree(s);
|
||||
s = NULL;
|
||||
|
||||
m_pos += n;
|
||||
|
||||
return out;
|
||||
|
||||
}
|
||||
|
||||
|
||||
std::string BinaryInput::readString() {
|
||||
int64 n = 0;
|
||||
|
||||
if ((m_pos + m_alreadyRead + n) < (m_length - 1)) {
|
||||
prepareToRead(1);
|
||||
}
|
||||
|
||||
if ( ((m_pos + m_alreadyRead + n) < (m_length - 1)) &&
|
||||
(m_buffer[m_pos + n] != '\0')) {
|
||||
|
||||
++n;
|
||||
while ( ((m_pos + m_alreadyRead + n) < (m_length - 1)) &&
|
||||
(m_buffer[m_pos + n] != '\0')) {
|
||||
|
||||
prepareToRead(1);
|
||||
++n;
|
||||
}
|
||||
}
|
||||
|
||||
// Consume NULL
|
||||
++n;
|
||||
|
||||
return readString(n);
|
||||
}
|
||||
|
||||
|
||||
std::string BinaryInput::readStringEven() {
|
||||
std::string x = readString();
|
||||
if (hasMore() && (G3D::isOdd(x.length() + 1))) {
|
||||
skip(1);
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
|
||||
std::string BinaryInput::readString32() {
|
||||
int len = readUInt32();
|
||||
return readString(len);
|
||||
}
|
||||
|
||||
|
||||
Vector4 BinaryInput::readVector4() {
|
||||
float x = readFloat32();
|
||||
float y = readFloat32();
|
||||
float z = readFloat32();
|
||||
float w = readFloat32();
|
||||
return Vector4(x, y, z, w);
|
||||
}
|
||||
|
||||
|
||||
Vector3 BinaryInput::readVector3() {
|
||||
float x = readFloat32();
|
||||
float y = readFloat32();
|
||||
float z = readFloat32();
|
||||
return Vector3(x, y, z);
|
||||
}
|
||||
|
||||
|
||||
Vector2 BinaryInput::readVector2() {
|
||||
float x = readFloat32();
|
||||
float y = readFloat32();
|
||||
return Vector2(x, y);
|
||||
}
|
||||
|
||||
|
||||
Color4 BinaryInput::readColor4() {
|
||||
float r = readFloat32();
|
||||
float g = readFloat32();
|
||||
float b = readFloat32();
|
||||
float a = readFloat32();
|
||||
return Color4(r, g, b, a);
|
||||
}
|
||||
|
||||
|
||||
Color3 BinaryInput::readColor3() {
|
||||
float r = readFloat32();
|
||||
float g = readFloat32();
|
||||
float b = readFloat32();
|
||||
return Color3(r, g, b);
|
||||
}
|
||||
|
||||
|
||||
void BinaryInput::beginBits() {
|
||||
debugAssert(m_beginEndBits == 0);
|
||||
m_beginEndBits = 1;
|
||||
m_bitPos = 0;
|
||||
|
||||
debugAssertM(hasMore(), "Can't call beginBits when at the end of a file");
|
||||
m_bitString = readUInt8();
|
||||
}
|
||||
|
||||
|
||||
uint32 BinaryInput::readBits(int numBits) {
|
||||
debugAssert(m_beginEndBits == 1);
|
||||
|
||||
uint32 out = 0;
|
||||
|
||||
const int total = numBits;
|
||||
while (numBits > 0) {
|
||||
if (m_bitPos > 7) {
|
||||
// Consume a new byte for reading. We do this at the beginning
|
||||
// of the loop so that we don't try to read past the end of the file.
|
||||
m_bitPos = 0;
|
||||
m_bitString = readUInt8();
|
||||
}
|
||||
|
||||
// Slide the lowest bit of the bitString into
|
||||
// the correct position.
|
||||
out |= (m_bitString & 1) << (total - numBits);
|
||||
|
||||
// Shift over to the next bit
|
||||
m_bitString = m_bitString >> 1;
|
||||
++m_bitPos;
|
||||
--numBits;
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
void BinaryInput::endBits() {
|
||||
debugAssert(m_beginEndBits == 1);
|
||||
if (m_bitPos == 0) {
|
||||
// Put back the last byte we read
|
||||
--m_pos;
|
||||
}
|
||||
m_beginEndBits = 0;
|
||||
m_bitPos = 0;
|
||||
}
|
||||
|
||||
}
|
||||
522
externals/g3dlite/BinaryOutput.cpp
vendored
Normal file
522
externals/g3dlite/BinaryOutput.cpp
vendored
Normal file
@@ -0,0 +1,522 @@
|
||||
/**
|
||||
@file BinaryOutput.cpp
|
||||
|
||||
@author Morgan McGuire, graphics3d.com
|
||||
Copyright 2002-2007, Morgan McGuire, All rights reserved.
|
||||
|
||||
@created 2002-02-20
|
||||
@edited 2008-01-07
|
||||
*/
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/BinaryOutput.h"
|
||||
#include "G3D/fileutils.h"
|
||||
#include "G3D/stringutils.h"
|
||||
#include "G3D/Array.h"
|
||||
#include <zlib.h>
|
||||
|
||||
#include <cstring>
|
||||
|
||||
// Largest memory buffer that the system will use for writing to
|
||||
// disk. After this (or if the system runs out of memory)
|
||||
// chunks of the file will be dumped to disk.
|
||||
//
|
||||
// Currently 400 MB
|
||||
#define MAX_BINARYOUTPUT_BUFFER_SIZE 400000000
|
||||
|
||||
namespace G3D {
|
||||
|
||||
void BinaryOutput::writeBool8(const std::vector<bool>& out, int n) {
|
||||
for (int i = 0; i < n; ++i) {
|
||||
writeBool8(out[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void BinaryOutput::writeBool8(const Array<bool>& out, int n) {
|
||||
writeBool8(out.getCArray(), n);
|
||||
}
|
||||
|
||||
#define IMPLEMENT_WRITER(ucase, lcase)\
|
||||
void BinaryOutput::write##ucase(const std::vector<lcase>& out, int n) {\
|
||||
write##ucase(&out[0], n);\
|
||||
}\
|
||||
\
|
||||
\
|
||||
void BinaryOutput::write##ucase(const Array<lcase>& out, int n) {\
|
||||
write##ucase(out.getCArray(), n);\
|
||||
}
|
||||
|
||||
|
||||
IMPLEMENT_WRITER(UInt8, uint8)
|
||||
IMPLEMENT_WRITER(Int8, int8)
|
||||
IMPLEMENT_WRITER(UInt16, uint16)
|
||||
IMPLEMENT_WRITER(Int16, int16)
|
||||
IMPLEMENT_WRITER(UInt32, uint32)
|
||||
IMPLEMENT_WRITER(Int32, int32)
|
||||
IMPLEMENT_WRITER(UInt64, uint64)
|
||||
IMPLEMENT_WRITER(Int64, int64)
|
||||
IMPLEMENT_WRITER(Float32, float32)
|
||||
IMPLEMENT_WRITER(Float64, float64)
|
||||
|
||||
#undef IMPLEMENT_WRITER
|
||||
|
||||
// Data structures that are one byte per element can be
|
||||
// directly copied, regardles of endian-ness.
|
||||
#define IMPLEMENT_WRITER(ucase, lcase)\
|
||||
void BinaryOutput::write##ucase(const lcase* out, int n) {\
|
||||
if (sizeof(lcase) == 1) {\
|
||||
writeBytes((void*)out, n);\
|
||||
} else {\
|
||||
for (int i = 0; i < n ; ++i) {\
|
||||
write##ucase(out[i]);\
|
||||
}\
|
||||
}\
|
||||
}
|
||||
|
||||
IMPLEMENT_WRITER(Bool8, bool)
|
||||
IMPLEMENT_WRITER(UInt8, uint8)
|
||||
IMPLEMENT_WRITER(Int8, int8)
|
||||
|
||||
#undef IMPLEMENT_WRITER
|
||||
|
||||
|
||||
#define IMPLEMENT_WRITER(ucase, lcase)\
|
||||
void BinaryOutput::write##ucase(const lcase* out, int n) {\
|
||||
if (m_swapBytes) {\
|
||||
for (int i = 0; i < n; ++i) {\
|
||||
write##ucase(out[i]);\
|
||||
}\
|
||||
} else {\
|
||||
writeBytes((const void*)out, sizeof(lcase) * n);\
|
||||
}\
|
||||
}
|
||||
|
||||
|
||||
IMPLEMENT_WRITER(UInt16, uint16)
|
||||
IMPLEMENT_WRITER(Int16, int16)
|
||||
IMPLEMENT_WRITER(UInt32, uint32)
|
||||
IMPLEMENT_WRITER(Int32, int32)
|
||||
IMPLEMENT_WRITER(UInt64, uint64)
|
||||
IMPLEMENT_WRITER(Int64, int64)
|
||||
IMPLEMENT_WRITER(Float32, float32)
|
||||
IMPLEMENT_WRITER(Float64, float64)
|
||||
|
||||
#undef IMPLEMENT_WRITER
|
||||
|
||||
|
||||
void BinaryOutput::reallocBuffer(size_t bytes, size_t oldBufferLen) {
|
||||
//debugPrintf("reallocBuffer(%d, %d)\n", bytes, oldBufferLen);
|
||||
|
||||
size_t newBufferLen = (int)(m_bufferLen * 1.5) + 100;
|
||||
uint8* newBuffer = NULL;
|
||||
|
||||
if ((m_filename == "<memory>") || (newBufferLen < MAX_BINARYOUTPUT_BUFFER_SIZE)) {
|
||||
// We're either writing to memory (in which case we *have* to try and allocate)
|
||||
// or we've been asked to allocate a reasonable size buffer.
|
||||
|
||||
//debugPrintf(" realloc(%d)\n", newBufferLen);
|
||||
newBuffer = (uint8*)System::realloc(m_buffer, newBufferLen);
|
||||
if (newBuffer != NULL) {
|
||||
m_maxBufferLen = newBufferLen;
|
||||
}
|
||||
}
|
||||
|
||||
if ((newBuffer == NULL) && (bytes > 0)) {
|
||||
// Realloc failed; we're probably out of memory. Back out
|
||||
// the entire call and try to dump some data to disk.
|
||||
m_bufferLen = oldBufferLen;
|
||||
reserveBytesWhenOutOfMemory(bytes);
|
||||
} else {
|
||||
m_buffer = newBuffer;
|
||||
debugAssert(isValidHeapPointer(m_buffer));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void BinaryOutput::reserveBytesWhenOutOfMemory(size_t bytes) {
|
||||
if (m_filename == "<memory>") {
|
||||
throw "Out of memory while writing to memory in BinaryOutput (no RAM left).";
|
||||
} else if ((int)bytes > (int)m_maxBufferLen) {
|
||||
throw "Out of memory while writing to disk in BinaryOutput (could not create a large enough buffer).";
|
||||
} else {
|
||||
|
||||
// Dump the contents to disk. In order to enable seeking backwards,
|
||||
// we keep the last 10 MB in memory.
|
||||
int writeBytes = m_bufferLen - 10 * 1024 * 1024;
|
||||
|
||||
if (writeBytes < m_bufferLen / 3) {
|
||||
// We're going to write less than 1/3 of the file;
|
||||
// give up and just write the whole thing.
|
||||
writeBytes = m_bufferLen;
|
||||
}
|
||||
debugAssert(writeBytes > 0);
|
||||
|
||||
//debugPrintf("Writing %d bytes to disk\n", writeBytes);
|
||||
|
||||
const char* mode = (m_alreadyWritten > 0) ? "ab" : "wb";
|
||||
FILE* file = fopen(m_filename.c_str(), mode);
|
||||
debugAssert(file);
|
||||
|
||||
size_t count = fwrite(m_buffer, 1, writeBytes, file);
|
||||
debugAssert((int)count == writeBytes); (void)count;
|
||||
|
||||
fclose(file);
|
||||
file = NULL;
|
||||
|
||||
// Record that we saved this data.
|
||||
m_alreadyWritten += writeBytes;
|
||||
m_bufferLen -= writeBytes;
|
||||
m_pos -= writeBytes;
|
||||
|
||||
debugAssert(m_bufferLen < m_maxBufferLen);
|
||||
debugAssert(m_bufferLen >= 0);
|
||||
debugAssert(m_pos >= 0);
|
||||
debugAssert(m_pos <= m_bufferLen);
|
||||
|
||||
// Shift the unwritten data back appropriately in the buffer.
|
||||
debugAssert(isValidHeapPointer(m_buffer));
|
||||
System::memcpy(m_buffer, m_buffer + writeBytes, m_bufferLen);
|
||||
debugAssert(isValidHeapPointer(m_buffer));
|
||||
|
||||
// *now* we allocate bytes (there should presumably be enough
|
||||
// space in the buffer; if not, we'll come back through this
|
||||
// code and dump the last 10MB to disk as well. Note that the
|
||||
// bytes > maxBufferLen case above would already have triggered
|
||||
// if this call couldn't succeed.
|
||||
reserveBytes(bytes);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
BinaryOutput::BinaryOutput() {
|
||||
m_alreadyWritten = 0;
|
||||
m_swapBytes = false;
|
||||
m_pos = 0;
|
||||
m_filename = "<memory>";
|
||||
m_buffer = NULL;
|
||||
m_bufferLen = 0;
|
||||
m_maxBufferLen = 0;
|
||||
m_beginEndBits = 0;
|
||||
m_bitString = 0;
|
||||
m_bitPos = 0;
|
||||
m_ok = true;
|
||||
m_committed = false;
|
||||
}
|
||||
|
||||
|
||||
BinaryOutput::BinaryOutput(
|
||||
const std::string& filename,
|
||||
G3DEndian fileEndian) {
|
||||
|
||||
m_pos = 0;
|
||||
m_alreadyWritten = 0;
|
||||
setEndian(fileEndian);
|
||||
m_filename = filename;
|
||||
m_buffer = NULL;
|
||||
m_bufferLen = 0;
|
||||
m_maxBufferLen = 0;
|
||||
m_beginEndBits = 0;
|
||||
m_bitString = 0;
|
||||
m_bitPos = 0;
|
||||
m_committed = false;
|
||||
|
||||
m_ok = true;
|
||||
/** Verify ability to write to disk */
|
||||
commit(false);
|
||||
m_committed = false;
|
||||
}
|
||||
|
||||
|
||||
void BinaryOutput::reset() {
|
||||
debugAssert(m_beginEndBits == 0);
|
||||
alwaysAssertM(m_filename == "<memory>",
|
||||
"Can only reset a BinaryOutput that writes to memory.");
|
||||
|
||||
// Do not reallocate, just clear the size of the buffer.
|
||||
m_pos = 0;
|
||||
m_alreadyWritten = 0;
|
||||
m_bufferLen = 0;
|
||||
m_beginEndBits = 0;
|
||||
m_bitString = 0;
|
||||
m_bitPos = 0;
|
||||
m_committed = false;
|
||||
}
|
||||
|
||||
|
||||
BinaryOutput::~BinaryOutput() {
|
||||
debugAssert((m_buffer == NULL) || isValidHeapPointer(m_buffer));
|
||||
System::free(m_buffer);
|
||||
m_buffer = NULL;
|
||||
m_bufferLen = 0;
|
||||
m_maxBufferLen = 0;
|
||||
}
|
||||
|
||||
|
||||
void BinaryOutput::setEndian(G3DEndian fileEndian) {
|
||||
m_fileEndian = fileEndian;
|
||||
m_swapBytes = (fileEndian != System::machineEndian());
|
||||
}
|
||||
|
||||
|
||||
bool BinaryOutput::ok() const {
|
||||
return m_ok;
|
||||
}
|
||||
|
||||
|
||||
void BinaryOutput::compress() {
|
||||
if (m_alreadyWritten > 0) {
|
||||
throw "Cannot compress huge files (part of this file has already been written to disk).";
|
||||
}
|
||||
|
||||
// Old buffer size
|
||||
int L = m_bufferLen;
|
||||
uint8* convert = (uint8*)&L;
|
||||
|
||||
// Zlib requires the output buffer to be this big
|
||||
unsigned long newSize = iCeil(m_bufferLen * 1.01) + 12;
|
||||
uint8* temp = (uint8*)System::malloc(newSize);
|
||||
int result = compress2(temp, &newSize, m_buffer, m_bufferLen, 9);
|
||||
|
||||
debugAssert(result == Z_OK); (void)result;
|
||||
|
||||
// Write the header
|
||||
if (m_swapBytes) {
|
||||
m_buffer[0] = convert[3];
|
||||
m_buffer[1] = convert[2];
|
||||
m_buffer[2] = convert[1];
|
||||
m_buffer[3] = convert[0];
|
||||
} else {
|
||||
m_buffer[0] = convert[0];
|
||||
m_buffer[1] = convert[1];
|
||||
m_buffer[2] = convert[2];
|
||||
m_buffer[3] = convert[3];
|
||||
}
|
||||
|
||||
// Write the data
|
||||
if ((int64)newSize + 4 > (int64)m_maxBufferLen) {
|
||||
m_maxBufferLen = newSize + 4;
|
||||
m_buffer = (uint8*)System::realloc(m_buffer, m_maxBufferLen);
|
||||
}
|
||||
m_bufferLen = newSize + 4;
|
||||
System::memcpy(m_buffer + 4, temp, newSize);
|
||||
m_pos = m_bufferLen;
|
||||
|
||||
System::free(temp);
|
||||
}
|
||||
|
||||
|
||||
void BinaryOutput::commit(bool flush) {
|
||||
debugAssertM(! m_committed, "Cannot commit twice");
|
||||
m_committed = true;
|
||||
debugAssertM(m_beginEndBits == 0, "Missing endBits before commit");
|
||||
|
||||
// Make sure the directory exists.
|
||||
std::string root, base, ext, path;
|
||||
Array<std::string> pathArray;
|
||||
parseFilename(m_filename, root, pathArray, base, ext);
|
||||
|
||||
path = root + stringJoin(pathArray, '/');
|
||||
if (! fileExists(path, false)) {
|
||||
createDirectory(path);
|
||||
}
|
||||
|
||||
const char* mode = (m_alreadyWritten > 0) ? "ab" : "wb";
|
||||
|
||||
FILE* file = fopen(m_filename.c_str(), mode);
|
||||
|
||||
m_ok = (file != NULL) && m_ok;
|
||||
|
||||
if (m_ok) {
|
||||
debugAssertM(file, std::string("Could not open '") + m_filename + "'");
|
||||
|
||||
if (m_buffer != NULL) {
|
||||
m_alreadyWritten += m_bufferLen;
|
||||
|
||||
int success = fwrite(m_buffer, m_bufferLen, 1, file);
|
||||
(void)success;
|
||||
debugAssertM(success == 1, std::string("Could not write to '") + m_filename + "'");
|
||||
}
|
||||
if (flush) {
|
||||
fflush(file);
|
||||
}
|
||||
fclose(file);
|
||||
file = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void BinaryOutput::commit(
|
||||
uint8* out) {
|
||||
debugAssertM(! m_committed, "Cannot commit twice");
|
||||
m_committed = true;
|
||||
|
||||
System::memcpy(out, m_buffer, m_bufferLen);
|
||||
}
|
||||
|
||||
|
||||
void BinaryOutput::writeUInt16(uint16 u) {
|
||||
reserveBytes(2);
|
||||
|
||||
uint8* convert = (uint8*)&u;
|
||||
|
||||
if (m_swapBytes) {
|
||||
m_buffer[m_pos] = convert[1];
|
||||
m_buffer[m_pos + 1] = convert[0];
|
||||
} else {
|
||||
*(uint16*)(m_buffer + m_pos) = u;
|
||||
}
|
||||
|
||||
m_pos += 2;
|
||||
}
|
||||
|
||||
|
||||
void BinaryOutput::writeUInt32(uint32 u) {
|
||||
reserveBytes(4);
|
||||
|
||||
uint8* convert = (uint8*)&u;
|
||||
|
||||
debugAssert(m_beginEndBits == 0);
|
||||
|
||||
if (m_swapBytes) {
|
||||
m_buffer[m_pos] = convert[3];
|
||||
m_buffer[m_pos + 1] = convert[2];
|
||||
m_buffer[m_pos + 2] = convert[1];
|
||||
m_buffer[m_pos + 3] = convert[0];
|
||||
} else {
|
||||
*(uint32*)(m_buffer + m_pos) = u;
|
||||
}
|
||||
|
||||
m_pos += 4;
|
||||
}
|
||||
|
||||
|
||||
void BinaryOutput::writeUInt64(uint64 u) {
|
||||
reserveBytes(8);
|
||||
|
||||
uint8* convert = (uint8*)&u;
|
||||
|
||||
if (m_swapBytes) {
|
||||
m_buffer[m_pos] = convert[7];
|
||||
m_buffer[m_pos + 1] = convert[6];
|
||||
m_buffer[m_pos + 2] = convert[5];
|
||||
m_buffer[m_pos + 3] = convert[4];
|
||||
m_buffer[m_pos + 4] = convert[3];
|
||||
m_buffer[m_pos + 5] = convert[2];
|
||||
m_buffer[m_pos + 6] = convert[1];
|
||||
m_buffer[m_pos + 7] = convert[0];
|
||||
} else {
|
||||
*(uint64*)(m_buffer + m_pos) = u;
|
||||
}
|
||||
|
||||
m_pos += 8;
|
||||
}
|
||||
|
||||
|
||||
void BinaryOutput::writeString(const char* s) {
|
||||
// +1 is because strlen doesn't count the null
|
||||
int len = strlen(s) + 1;
|
||||
|
||||
debugAssert(m_beginEndBits == 0);
|
||||
reserveBytes(len);
|
||||
System::memcpy(m_buffer + m_pos, s, len);
|
||||
m_pos += len;
|
||||
}
|
||||
|
||||
|
||||
void BinaryOutput::writeStringEven(const char* s) {
|
||||
// +1 is because strlen doesn't count the null
|
||||
int len = strlen(s) + 1;
|
||||
|
||||
reserveBytes(len);
|
||||
System::memcpy(m_buffer + m_pos, s, len);
|
||||
m_pos += len;
|
||||
|
||||
// Pad with another NULL
|
||||
if ((len % 2) == 1) {
|
||||
writeUInt8(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void BinaryOutput::writeString32(const char* s) {
|
||||
writeUInt32(strlen(s) + 1);
|
||||
writeString(s);
|
||||
}
|
||||
|
||||
|
||||
void BinaryOutput::writeVector4(const Vector4& v) {
|
||||
writeFloat32(v.x);
|
||||
writeFloat32(v.y);
|
||||
writeFloat32(v.z);
|
||||
writeFloat32(v.w);
|
||||
}
|
||||
|
||||
|
||||
void BinaryOutput::writeVector3(const Vector3& v) {
|
||||
writeFloat32(v.x);
|
||||
writeFloat32(v.y);
|
||||
writeFloat32(v.z);
|
||||
}
|
||||
|
||||
|
||||
void BinaryOutput::writeVector2(const Vector2& v) {
|
||||
writeFloat32(v.x);
|
||||
writeFloat32(v.y);
|
||||
}
|
||||
|
||||
|
||||
void BinaryOutput::writeColor4(const Color4& v) {
|
||||
writeFloat32(v.r);
|
||||
writeFloat32(v.g);
|
||||
writeFloat32(v.b);
|
||||
writeFloat32(v.a);
|
||||
}
|
||||
|
||||
|
||||
void BinaryOutput::writeColor3(const Color3& v) {
|
||||
writeFloat32(v.r);
|
||||
writeFloat32(v.g);
|
||||
writeFloat32(v.b);
|
||||
}
|
||||
|
||||
|
||||
void BinaryOutput::beginBits() {
|
||||
debugAssertM(m_beginEndBits == 0, "Already in beginBits...endBits");
|
||||
m_bitString = 0x00;
|
||||
m_bitPos = 0;
|
||||
m_beginEndBits = 1;
|
||||
}
|
||||
|
||||
|
||||
void BinaryOutput::writeBits(uint32 value, int numBits) {
|
||||
|
||||
while (numBits > 0) {
|
||||
// Extract the current bit of value and
|
||||
// insert it into the current byte
|
||||
m_bitString |= (value & 1) << m_bitPos;
|
||||
++m_bitPos;
|
||||
value = value >> 1;
|
||||
--numBits;
|
||||
|
||||
if (m_bitPos > 7) {
|
||||
// We've reached the end of this byte
|
||||
writeUInt8(m_bitString);
|
||||
m_bitString = 0x00;
|
||||
m_bitPos = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void BinaryOutput::endBits() {
|
||||
debugAssertM(m_beginEndBits == 1, "Not in beginBits...endBits");
|
||||
if (m_bitPos > 0) {
|
||||
writeUInt8(m_bitString);
|
||||
}
|
||||
m_bitString = 0;
|
||||
m_bitPos = 0;
|
||||
m_beginEndBits = 0;
|
||||
}
|
||||
|
||||
}
|
||||
393
externals/g3dlite/Box.cpp
vendored
Normal file
393
externals/g3dlite/Box.cpp
vendored
Normal file
@@ -0,0 +1,393 @@
|
||||
/**
|
||||
@file Box.cpp
|
||||
Box class
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
@created 2001-06-02
|
||||
@edited 2006-02-05
|
||||
*/
|
||||
|
||||
#include "G3D/Box.h"
|
||||
#include "G3D/debug.h"
|
||||
#include "G3D/Plane.h"
|
||||
#include "G3D/AABox.h"
|
||||
#include "G3D/CoordinateFrame.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
/**
|
||||
Sets a field on four vertices. Used by the constructor.
|
||||
*/
|
||||
#define setMany(i0, i1, i2, i3, field, extreme) \
|
||||
_corner[i0].field = _corner[i1].field = \
|
||||
_corner[i2].field = _corner[i3].field = \
|
||||
(extreme).field
|
||||
|
||||
Box::Box() {
|
||||
}
|
||||
|
||||
|
||||
Box::Box(const AABox& b) {
|
||||
init(b.low(), b.high());
|
||||
}
|
||||
|
||||
Box::Box(class BinaryInput& b) {
|
||||
deserialize(b);
|
||||
}
|
||||
|
||||
|
||||
void Box::serialize(class BinaryOutput& b) const {
|
||||
int i;
|
||||
for (i = 0; i < 8; ++i) {
|
||||
_corner[i].serialize(b);
|
||||
}
|
||||
|
||||
// Other state can be reconstructed
|
||||
}
|
||||
|
||||
|
||||
void Box::deserialize(class BinaryInput& b) {
|
||||
int i;
|
||||
|
||||
_center = Vector3::zero();
|
||||
for (i = 0; i < 8; ++i) {
|
||||
_corner[i].deserialize(b);
|
||||
_center += _corner[i];
|
||||
}
|
||||
|
||||
_center = _center / 8;
|
||||
|
||||
// Reconstruct other state from the corners
|
||||
_axis[0] = _corner[5] - _corner[4];
|
||||
_axis[1] = _corner[7] - _corner[4];
|
||||
_axis[2] = _corner[0] - _corner[4];
|
||||
|
||||
for (i = 0; i < 3; ++i) {
|
||||
_extent[i] = _axis[i].magnitude();
|
||||
_axis[i] /= _extent[i];
|
||||
}
|
||||
|
||||
_volume = _extent.x * _extent.y * _extent.z;
|
||||
|
||||
_area = 2 *
|
||||
(_extent.x * _extent.y +
|
||||
_extent.y * _extent.z +
|
||||
_extent.z * _extent.x);
|
||||
}
|
||||
|
||||
|
||||
Box::Box(
|
||||
const Vector3& min,
|
||||
const Vector3& max) {
|
||||
|
||||
init(min.min(max), min.max(max));
|
||||
|
||||
}
|
||||
|
||||
void Box::init(
|
||||
const Vector3& min,
|
||||
const Vector3& max) {
|
||||
|
||||
debugAssert(
|
||||
(min.x <= max.x) &&
|
||||
(min.y <= max.y) &&
|
||||
(min.z <= max.z));
|
||||
|
||||
setMany(0, 1, 2, 3, z, max);
|
||||
setMany(4, 5, 6, 7, z, min);
|
||||
|
||||
setMany(1, 2, 5, 6, x, max);
|
||||
setMany(0, 3, 4, 7, x, min);
|
||||
|
||||
setMany(3, 2, 6, 7, y, max);
|
||||
setMany(0, 1, 5, 4, y, min);
|
||||
|
||||
_extent = max - min;
|
||||
|
||||
_axis[0] = Vector3::unitX();
|
||||
_axis[1] = Vector3::unitY();
|
||||
_axis[2] = Vector3::unitZ();
|
||||
|
||||
if (_extent.isFinite()) {
|
||||
_volume = _extent.x * _extent.y * _extent.z;
|
||||
} else {
|
||||
_volume = G3D::finf();
|
||||
}
|
||||
|
||||
debugAssert(! isNaN(_extent.x));
|
||||
|
||||
_area = 2 *
|
||||
(_extent.x * _extent.y +
|
||||
_extent.y * _extent.z +
|
||||
_extent.z * _extent.x);
|
||||
|
||||
_center = (max + min) * 0.5f;
|
||||
|
||||
// If the extent is infinite along an axis, make the center zero to avoid NaNs
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
if (! G3D::isFinite(_extent[i])) {
|
||||
_center[i] = 0.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
float Box::volume() const {
|
||||
return _volume;
|
||||
}
|
||||
|
||||
|
||||
float Box::area() const {
|
||||
return _area;
|
||||
}
|
||||
|
||||
|
||||
void Box::getLocalFrame(CoordinateFrame& frame) const {
|
||||
|
||||
frame.rotation = Matrix3(
|
||||
_axis[0][0], _axis[1][0], _axis[2][0],
|
||||
_axis[0][1], _axis[1][1], _axis[2][1],
|
||||
_axis[0][2], _axis[1][2], _axis[2][2]);
|
||||
|
||||
frame.translation = _center;
|
||||
}
|
||||
|
||||
|
||||
CoordinateFrame Box::localFrame() const {
|
||||
CoordinateFrame out;
|
||||
getLocalFrame(out);
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
void Box::getFaceCorners(int f, Vector3& v0, Vector3& v1, Vector3& v2, Vector3& v3) const {
|
||||
switch (f) {
|
||||
case 0:
|
||||
v0 = _corner[0]; v1 = _corner[1]; v2 = _corner[2]; v3 = _corner[3];
|
||||
break;
|
||||
|
||||
case 1:
|
||||
v0 = _corner[1]; v1 = _corner[5]; v2 = _corner[6]; v3 = _corner[2];
|
||||
break;
|
||||
|
||||
case 2:
|
||||
v0 = _corner[7]; v1 = _corner[6]; v2 = _corner[5]; v3 = _corner[4];
|
||||
break;
|
||||
|
||||
case 3:
|
||||
v0 = _corner[2]; v1 = _corner[6]; v2 = _corner[7]; v3 = _corner[3];
|
||||
break;
|
||||
|
||||
case 4:
|
||||
v0 = _corner[3]; v1 = _corner[7]; v2 = _corner[4]; v3 = _corner[0];
|
||||
break;
|
||||
|
||||
case 5:
|
||||
v0 = _corner[1]; v1 = _corner[0]; v2 = _corner[4]; v3 = _corner[5];
|
||||
break;
|
||||
|
||||
default:
|
||||
debugAssert((f >= 0) && (f < 6));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
int Box::dummy = 0;
|
||||
|
||||
bool Box::culledBy(
|
||||
const Array<Plane>& plane,
|
||||
int& cullingPlane,
|
||||
const uint32 _inMask,
|
||||
uint32& childMask) const {
|
||||
|
||||
uint32 inMask = _inMask;
|
||||
assert(plane.size() < 31);
|
||||
|
||||
childMask = 0;
|
||||
|
||||
// See if there is one plane for which all of the
|
||||
// vertices are in the negative half space.
|
||||
for (int p = 0; p < plane.size(); ++p) {
|
||||
|
||||
// Only test planes that are not masked
|
||||
if ((inMask & 1) != 0) {
|
||||
|
||||
Vector3 corner;
|
||||
|
||||
int numContained = 0;
|
||||
int v = 0;
|
||||
|
||||
// We can early-out only if we have found one point on each
|
||||
// side of the plane (i.e. if we are straddling). That
|
||||
// occurs when (numContained < v) && (numContained > 0)
|
||||
for (v = 0; (v < 8) && ((numContained == v) || (numContained == 0)); ++v) {
|
||||
if (plane[p].halfSpaceContains(_corner[v])) {
|
||||
++numContained;
|
||||
}
|
||||
}
|
||||
|
||||
if (numContained == 0) {
|
||||
// Plane p culled the box
|
||||
cullingPlane = p;
|
||||
|
||||
// The caller should not recurse into the children,
|
||||
// since the parent is culled. If they do recurse,
|
||||
// make them only test against this one plane, which
|
||||
// will immediately cull the volume.
|
||||
childMask = 1 << p;
|
||||
return true;
|
||||
|
||||
} else if (numContained < v) {
|
||||
// The bounding volume straddled the plane; we have
|
||||
// to keep testing against this plane
|
||||
childMask |= (1 << p);
|
||||
}
|
||||
}
|
||||
|
||||
// Move on to the next bit.
|
||||
inMask = inMask >> 1;
|
||||
}
|
||||
|
||||
// None of the planes could cull this box
|
||||
cullingPlane = -1;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Box::culledBy(
|
||||
const Array<Plane>& plane,
|
||||
int& cullingPlane,
|
||||
const uint32 _inMask) const {
|
||||
|
||||
uint32 inMask = _inMask;
|
||||
assert(plane.size() < 31);
|
||||
|
||||
// See if there is one plane for which all of the
|
||||
// vertices are in the negative half space.
|
||||
for (int p = 0; p < plane.size(); ++p) {
|
||||
|
||||
// Only test planes that are not masked
|
||||
if ((inMask & 1) != 0) {
|
||||
|
||||
bool culled = true;
|
||||
|
||||
int v;
|
||||
|
||||
// Assume this plane culls all points. See if there is a point
|
||||
// not culled by the plane... early out when at least one point
|
||||
// is in the positive half space.
|
||||
for (v = 0; (v < 8) && culled; ++v) {
|
||||
culled = ! plane[p].halfSpaceContains(corner(v));
|
||||
}
|
||||
|
||||
if (culled) {
|
||||
// Plane p culled the box
|
||||
cullingPlane = p;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Move on to the next bit.
|
||||
inMask = inMask >> 1;
|
||||
}
|
||||
|
||||
// None of the planes could cull this box
|
||||
cullingPlane = -1;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Box::contains(
|
||||
const Vector3& point) const {
|
||||
|
||||
// Form axes from three edges, transform the point into that
|
||||
// space, and perform 3 interval tests
|
||||
|
||||
Vector3 u = _corner[4] - _corner[0];
|
||||
Vector3 v = _corner[3] - _corner[0];
|
||||
Vector3 w = _corner[1] - _corner[0];
|
||||
|
||||
Matrix3 M = Matrix3(u.x, v.x, w.x,
|
||||
u.y, v.y, w.y,
|
||||
u.z, v.z, w.z);
|
||||
|
||||
// M^-1 * (point - _corner[0]) = point in unit cube's object space
|
||||
// compute the inverse of M
|
||||
Vector3 osPoint = M.inverse() * (point - _corner[0]);
|
||||
|
||||
return
|
||||
(osPoint.x >= 0) &&
|
||||
(osPoint.y >= 0) &&
|
||||
(osPoint.z >= 0) &&
|
||||
(osPoint.x <= 1) &&
|
||||
(osPoint.y <= 1) &&
|
||||
(osPoint.z <= 1);
|
||||
}
|
||||
|
||||
#undef setMany
|
||||
|
||||
|
||||
void Box::getRandomSurfacePoint(Vector3& P, Vector3& N) const {
|
||||
float aXY = _extent.x * _extent.y;
|
||||
float aYZ = _extent.y * _extent.z;
|
||||
float aZX = _extent.z * _extent.x;
|
||||
|
||||
float r = (float)uniformRandom(0, aXY + aYZ + aZX);
|
||||
|
||||
// Choose evenly between positive and negative face planes
|
||||
float d = (uniformRandom(0, 1) < 0.5f) ? -1.0f : 1.0f;
|
||||
|
||||
// The probability of choosing a given face is proportional to
|
||||
// its area.
|
||||
if (r < aXY) {
|
||||
P = _axis[0] * (float)uniformRandom(-0.5, 0.5) * _extent.x +
|
||||
_axis[1] * (float)uniformRandom(-0.5, 0.5) * _extent.y +
|
||||
_center + _axis[2] * d * _extent.z * 0.5f;
|
||||
N = _axis[2] * d;
|
||||
} else if (r < aYZ) {
|
||||
P = _axis[1] * (float)uniformRandom(-0.5, 0.5) * _extent.y +
|
||||
_axis[2] * (float)uniformRandom(-0.5, 0.5) * _extent.z +
|
||||
_center + _axis[0] * d * _extent.x * 0.5f;
|
||||
N = _axis[0] * d;
|
||||
} else {
|
||||
P = _axis[2] * (float)uniformRandom(-0.5, 0.5) * _extent.z +
|
||||
_axis[0] *(float) uniformRandom(-0.5, 0.5) * _extent.x +
|
||||
_center + _axis[1] * d * _extent.y * 0.5f;
|
||||
N = _axis[1] * d;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Vector3 Box::randomInteriorPoint() const {
|
||||
Vector3 sum = _center;
|
||||
|
||||
for (int a = 0; a < 3; ++a) {
|
||||
sum += _axis[a] * (float)uniformRandom(-0.5, 0.5) * _extent[a];
|
||||
}
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
Box Box::inf() {
|
||||
return Box(-Vector3::inf(), Vector3::inf());
|
||||
}
|
||||
|
||||
void Box::getBounds(class AABox& aabb) const {
|
||||
|
||||
Vector3 lo = _corner[0];
|
||||
Vector3 hi = lo;
|
||||
|
||||
for (int v = 1; v < 8; ++v) {
|
||||
const Vector3& C = _corner[v];
|
||||
lo = lo.min(C);
|
||||
hi = hi.max(C);
|
||||
}
|
||||
|
||||
aabb = AABox(lo, hi);
|
||||
}
|
||||
|
||||
|
||||
} // namespace
|
||||
11
externals/g3dlite/CMakeLists.txt
vendored
Normal file
11
externals/g3dlite/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
file(GLOB sources *.cpp)
|
||||
|
||||
SET(g3dlib_STAT_SRCS
|
||||
${sources}
|
||||
)
|
||||
|
||||
include_directories(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
)
|
||||
|
||||
add_library(g3dlib STATIC ${g3dlib_STAT_SRCS})
|
||||
179
externals/g3dlite/Capsule.cpp
vendored
Normal file
179
externals/g3dlite/Capsule.cpp
vendored
Normal file
@@ -0,0 +1,179 @@
|
||||
/**
|
||||
@file Capsule.cpp
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
@created 2003-02-07
|
||||
@edited 2005-08-18
|
||||
|
||||
Copyright 2000-2009, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
#include "G3D/Capsule.h"
|
||||
#include "G3D/BinaryInput.h"
|
||||
#include "G3D/BinaryOutput.h"
|
||||
#include "G3D/LineSegment.h"
|
||||
#include "G3D/Sphere.h"
|
||||
#include "G3D/CoordinateFrame.h"
|
||||
#include "G3D/Line.h"
|
||||
#include "G3D/AABox.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
Capsule::Capsule(class BinaryInput& b) {
|
||||
deserialize(b);
|
||||
}
|
||||
|
||||
|
||||
Capsule::Capsule() {
|
||||
}
|
||||
|
||||
|
||||
Capsule::Capsule(const Vector3& _p1, const Vector3& _p2, float _r)
|
||||
: p1(_p1), p2(_p2), _radius(_r) {
|
||||
}
|
||||
|
||||
|
||||
void Capsule::serialize(class BinaryOutput& b) const {
|
||||
p1.serialize(b);
|
||||
p2.serialize(b);
|
||||
b.writeFloat64(_radius);
|
||||
}
|
||||
|
||||
|
||||
void Capsule::deserialize(class BinaryInput& b) {
|
||||
p1.deserialize(b);
|
||||
p2.deserialize(b);
|
||||
_radius = b.readFloat64();
|
||||
}
|
||||
|
||||
|
||||
Line Capsule::axis() const {
|
||||
return Line::fromTwoPoints(p1, p2);
|
||||
}
|
||||
|
||||
|
||||
float Capsule::volume() const {
|
||||
return
|
||||
// Sphere volume
|
||||
pow(_radius, 3) * pi() * 4 / 3 +
|
||||
|
||||
// Cylinder volume
|
||||
pow(_radius, 2) * (p1 - p2).magnitude();
|
||||
}
|
||||
|
||||
|
||||
float Capsule::area() const {
|
||||
|
||||
return
|
||||
// Sphere area
|
||||
pow(_radius, 2) * 4 * pi() +
|
||||
|
||||
// Cylinder area
|
||||
twoPi() * _radius * (p1 - p2).magnitude();
|
||||
}
|
||||
|
||||
|
||||
void Capsule::getBounds(AABox& out) const {
|
||||
Vector3 min = p1.min(p2) - (Vector3(1, 1, 1) * _radius);
|
||||
Vector3 max = p1.max(p2) + (Vector3(1, 1, 1) * _radius);
|
||||
|
||||
out = AABox(min, max);
|
||||
}
|
||||
|
||||
|
||||
bool Capsule::contains(const Vector3& p) const {
|
||||
return LineSegment::fromTwoPoints(p1, p2).distanceSquared(p) <= square(radius());
|
||||
}
|
||||
|
||||
|
||||
void Capsule::getRandomSurfacePoint(Vector3& p, Vector3& N) const {
|
||||
float h = height();
|
||||
float r = radius();
|
||||
|
||||
// Create a random point on a standard capsule and then rotate to the global frame.
|
||||
|
||||
// Relative areas
|
||||
float capRelArea = sqrt(r) / 2.0f;
|
||||
float sideRelArea = r * h;
|
||||
|
||||
float r1 = uniformRandom(0, capRelArea * 2 + sideRelArea);
|
||||
|
||||
if (r1 < capRelArea * 2) {
|
||||
|
||||
// Select a point uniformly at random on a sphere
|
||||
N = Sphere(Vector3::zero(), 1).randomSurfacePoint();
|
||||
p = N * r;
|
||||
p.y += sign(p.y) * h / 2.0f;
|
||||
} else {
|
||||
// Side
|
||||
float a = uniformRandom(0, (float)twoPi());
|
||||
N.x = cos(a);
|
||||
N.y = 0;
|
||||
N.z = sin(a);
|
||||
p.x = N.x * r;
|
||||
p.z = N.y * r;
|
||||
p.y = uniformRandom(-h / 2.0f, h / 2.0f);
|
||||
}
|
||||
|
||||
// Transform to world space
|
||||
CoordinateFrame cframe;
|
||||
getReferenceFrame(cframe);
|
||||
|
||||
p = cframe.pointToWorldSpace(p);
|
||||
N = cframe.normalToWorldSpace(N);
|
||||
}
|
||||
|
||||
|
||||
void Capsule::getReferenceFrame(CoordinateFrame& cframe) const {
|
||||
cframe.translation = center();
|
||||
|
||||
Vector3 Y = (p1 - p2).direction();
|
||||
Vector3 X = (abs(Y.dot(Vector3::unitX())) > 0.9) ? Vector3::unitY() : Vector3::unitX();
|
||||
Vector3 Z = X.cross(Y).direction();
|
||||
X = Y.cross(Z);
|
||||
cframe.rotation.setColumn(0, X);
|
||||
cframe.rotation.setColumn(1, Y);
|
||||
cframe.rotation.setColumn(2, Z);
|
||||
}
|
||||
|
||||
|
||||
Vector3 Capsule::randomInteriorPoint() const {
|
||||
float h = height();
|
||||
float r = radius();
|
||||
|
||||
// Create a random point in a standard capsule and then rotate to the global frame.
|
||||
|
||||
Vector3 p;
|
||||
|
||||
float hemiVolume = pi() * (r*r*r) * 4 / 6.0;
|
||||
float cylVolume = pi() * square(r) * h;
|
||||
|
||||
float r1 = uniformRandom(0, 2.0 * hemiVolume + cylVolume);
|
||||
|
||||
if (r1 < 2.0 * hemiVolume) {
|
||||
|
||||
p = Sphere(Vector3::zero(), r).randomInteriorPoint();
|
||||
|
||||
p.y += sign(p.y) * h / 2.0f;
|
||||
|
||||
} else {
|
||||
|
||||
// Select a point uniformly at random on a disk
|
||||
float a = uniformRandom(0, (float)twoPi());
|
||||
float r2 = sqrt(uniformRandom(0, 1)) * r;
|
||||
|
||||
p = Vector3(cos(a) * r2,
|
||||
uniformRandom(-h / 2.0f, h / 2.0f),
|
||||
sin(a) * r2);
|
||||
}
|
||||
|
||||
// Transform to world space
|
||||
CoordinateFrame cframe;
|
||||
getReferenceFrame(cframe);
|
||||
|
||||
return cframe.pointToWorldSpace(p);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
2455
externals/g3dlite/CollisionDetection.cpp
vendored
Normal file
2455
externals/g3dlite/CollisionDetection.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
436
externals/g3dlite/CoordinateFrame.cpp
vendored
Normal file
436
externals/g3dlite/CoordinateFrame.cpp
vendored
Normal file
@@ -0,0 +1,436 @@
|
||||
/**
|
||||
@file CoordinateFrame.cpp
|
||||
|
||||
Coordinate frame class
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
@created 2001-06-02
|
||||
@edited 2009-11-13
|
||||
|
||||
Copyright 2000-2010, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/CoordinateFrame.h"
|
||||
#include "G3D/Quat.h"
|
||||
#include "G3D/Matrix4.h"
|
||||
#include "G3D/Box.h"
|
||||
#include "G3D/AABox.h"
|
||||
#include "G3D/Sphere.h"
|
||||
#include "G3D/Triangle.h"
|
||||
#include "G3D/Ray.h"
|
||||
#include "G3D/Capsule.h"
|
||||
#include "G3D/Cylinder.h"
|
||||
#include "G3D/UprightFrame.h"
|
||||
#include "G3D/Any.h"
|
||||
#include "G3D/stringutils.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
CoordinateFrame::CoordinateFrame(const Any& any) {
|
||||
any.verifyName("CFrame");
|
||||
if (toUpper(any.name()) == "CFRAME") {
|
||||
any.verifyType(Any::TABLE, Any::ARRAY);
|
||||
if (any.type() == Any::TABLE) {
|
||||
rotation = any["rotation"];
|
||||
translation = any["translation"];
|
||||
} else {
|
||||
any.verifySize(2);
|
||||
rotation = any[0];
|
||||
translation = any[1];
|
||||
}
|
||||
} else {
|
||||
any.verifyName("CFrame::fromXYZYPRDegrees");
|
||||
any.verifyType(Any::ARRAY);
|
||||
any.verifySize(3, 6);
|
||||
|
||||
int s = any.size();
|
||||
|
||||
*this = fromXYZYPRDegrees(any[0], any[1], any[2],
|
||||
(s > 3) ? any[3].number() : 0.0f,
|
||||
(s > 4) ? any[4].number() : 0.0f,
|
||||
(s > 5) ? any[5].number() : 0.0f);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
CoordinateFrame::operator Any() const {
|
||||
float x, y, z, yaw, pitch, roll;
|
||||
getXYZYPRDegrees(x, y, z, yaw, pitch, roll);
|
||||
Any a(Any::ARRAY, "CFrame::fromXYZYPRDegrees");
|
||||
a.append(x, y, z, yaw);
|
||||
if ( ! G3D::fuzzyEq(yaw, 0.0f) || ! G3D::fuzzyEq(pitch, 0.0f) || ! G3D::fuzzyEq(roll, 0.0f)) {
|
||||
a.append(yaw);
|
||||
if (! G3D::fuzzyEq(pitch, 0.0f) || ! G3D::fuzzyEq(roll, 0.0f)) {
|
||||
a.append(pitch);
|
||||
if (! G3D::fuzzyEq(roll, 0.0f)) {
|
||||
a.append(roll);
|
||||
}
|
||||
}
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
|
||||
CoordinateFrame::CoordinateFrame(const class UprightFrame& f) {
|
||||
*this = f.toCoordinateFrame();
|
||||
}
|
||||
|
||||
|
||||
CoordinateFrame::CoordinateFrame() :
|
||||
rotation(Matrix3::identity()), translation(Vector3::zero()) {
|
||||
}
|
||||
|
||||
CoordinateFrame CoordinateFrame::fromXYZYPRRadians(float x, float y, float z, float yaw,
|
||||
float pitch, float roll) {
|
||||
Matrix3 rotation = Matrix3::fromAxisAngle(Vector3::unitY(), yaw);
|
||||
|
||||
rotation = Matrix3::fromAxisAngle(rotation.column(0), pitch) * rotation;
|
||||
rotation = Matrix3::fromAxisAngle(rotation.column(2), roll) * rotation;
|
||||
|
||||
const Vector3 translation(x, y, z);
|
||||
|
||||
return CoordinateFrame(rotation, translation);
|
||||
}
|
||||
|
||||
|
||||
void CoordinateFrame::getXYZYPRRadians(float& x, float& y, float& z,
|
||||
float& yaw, float& pitch, float& roll) const {
|
||||
x = translation.x;
|
||||
y = translation.y;
|
||||
z = translation.z;
|
||||
|
||||
const Vector3& look = lookVector();
|
||||
|
||||
if (abs(look.y) > 0.99f) {
|
||||
// Looking nearly straight up or down
|
||||
|
||||
yaw = G3D::pi() + atan2(look.x, look.z);
|
||||
pitch = asin(look.y);
|
||||
roll = 0.0f;
|
||||
|
||||
} else {
|
||||
|
||||
// Yaw cannot be affected by others, so pull it first
|
||||
yaw = G3D::pi() + atan2(look.x, look.z);
|
||||
|
||||
// Pitch is the elevation of the yaw vector
|
||||
pitch = asin(look.y);
|
||||
|
||||
Vector3 actualRight = rightVector();
|
||||
Vector3 expectedRight = look.cross(Vector3::unitY());
|
||||
|
||||
roll = 0;//acos(actualRight.dot(expectedRight)); TODO
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CoordinateFrame::getXYZYPRDegrees(float& x, float& y, float& z,
|
||||
float& yaw, float& pitch, float& roll) const {
|
||||
getXYZYPRRadians(x, y, z, yaw, pitch, roll);
|
||||
yaw = toDegrees(yaw);
|
||||
pitch = toDegrees(pitch);
|
||||
roll = toDegrees(roll);
|
||||
}
|
||||
|
||||
|
||||
CoordinateFrame CoordinateFrame::fromXYZYPRDegrees(float x, float y, float z,
|
||||
float yaw, float pitch, float roll) {
|
||||
return fromXYZYPRRadians(x, y, z, toRadians(yaw), toRadians(pitch), toRadians(roll));
|
||||
}
|
||||
|
||||
|
||||
Ray CoordinateFrame::lookRay() const {
|
||||
return Ray::fromOriginAndDirection(translation, lookVector());
|
||||
}
|
||||
|
||||
|
||||
bool CoordinateFrame::fuzzyEq(const CoordinateFrame& other) const {
|
||||
|
||||
for (int c = 0; c < 3; ++c) {
|
||||
for (int r = 0; r < 3; ++r) {
|
||||
if (! G3D::fuzzyEq(other.rotation[r][c], rotation[r][c])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (! G3D::fuzzyEq(translation[c], other.translation[c])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool CoordinateFrame::fuzzyIsIdentity() const {
|
||||
const Matrix3& I = Matrix3::identity();
|
||||
|
||||
for (int c = 0; c < 3; ++c) {
|
||||
for (int r = 0; r < 3; ++r) {
|
||||
if (fuzzyNe(I[r][c], rotation[r][c])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (fuzzyNe(translation[c], 0)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool CoordinateFrame::isIdentity() const {
|
||||
return
|
||||
(translation == Vector3::zero()) &&
|
||||
(rotation == Matrix3::identity());
|
||||
}
|
||||
|
||||
|
||||
Matrix4 CoordinateFrame::toMatrix4() const {
|
||||
return Matrix4(*this);
|
||||
}
|
||||
|
||||
|
||||
std::string CoordinateFrame::toXML() const {
|
||||
return G3D::format(
|
||||
"<COORDINATEFRAME>\n %lf,%lf,%lf,%lf,\n %lf,%lf,%lf,%lf,\n %lf,%lf,%lf,%lf,\n %lf,%lf,%lf,%lf\n</COORDINATEFRAME>\n",
|
||||
rotation[0][0], rotation[0][1], rotation[0][2], translation.x,
|
||||
rotation[1][0], rotation[1][1], rotation[1][2], translation.y,
|
||||
rotation[2][0], rotation[2][1], rotation[2][2], translation.z,
|
||||
0.0, 0.0, 0.0, 1.0);
|
||||
}
|
||||
|
||||
|
||||
Plane CoordinateFrame::toObjectSpace(const Plane& p) const {
|
||||
Vector3 N, P;
|
||||
double d;
|
||||
p.getEquation(N, d);
|
||||
P = N * (float)d;
|
||||
P = pointToObjectSpace(P);
|
||||
N = normalToObjectSpace(N);
|
||||
return Plane(N, P);
|
||||
}
|
||||
|
||||
|
||||
Plane CoordinateFrame::toWorldSpace(const Plane& p) const {
|
||||
Vector3 N, P;
|
||||
double d;
|
||||
p.getEquation(N, d);
|
||||
P = N * (float)d;
|
||||
P = pointToWorldSpace(P);
|
||||
N = normalToWorldSpace(N);
|
||||
return Plane(N, P);
|
||||
}
|
||||
|
||||
|
||||
Triangle CoordinateFrame::toObjectSpace(const Triangle& t) const {
|
||||
return Triangle(pointToObjectSpace(t.vertex(0)),
|
||||
pointToObjectSpace(t.vertex(1)),
|
||||
pointToObjectSpace(t.vertex(2)));
|
||||
}
|
||||
|
||||
|
||||
Triangle CoordinateFrame::toWorldSpace(const Triangle& t) const {
|
||||
return Triangle(pointToWorldSpace(t.vertex(0)),
|
||||
pointToWorldSpace(t.vertex(1)),
|
||||
pointToWorldSpace(t.vertex(2)));
|
||||
}
|
||||
|
||||
|
||||
Cylinder CoordinateFrame::toWorldSpace(const Cylinder& c) const {
|
||||
return Cylinder(
|
||||
pointToWorldSpace(c.point(0)),
|
||||
pointToWorldSpace(c.point(1)),
|
||||
c.radius());
|
||||
}
|
||||
|
||||
|
||||
Capsule CoordinateFrame::toWorldSpace(const Capsule& c) const {
|
||||
return Capsule(
|
||||
pointToWorldSpace(c.point(0)),
|
||||
pointToWorldSpace(c.point(1)),
|
||||
c.radius());
|
||||
}
|
||||
|
||||
|
||||
Box CoordinateFrame::toWorldSpace(const AABox& b) const {
|
||||
Box b2(b);
|
||||
return toWorldSpace(b2);
|
||||
}
|
||||
|
||||
|
||||
Box CoordinateFrame::toWorldSpace(const Box& b) const {
|
||||
Box out(b);
|
||||
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
out._corner[i] = pointToWorldSpace(b._corner[i]);
|
||||
debugAssert(! isNaN(out._corner[i].x));
|
||||
}
|
||||
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
out._axis[i] = vectorToWorldSpace(b._axis[i]);
|
||||
}
|
||||
|
||||
out._center = pointToWorldSpace(b._center);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
Box CoordinateFrame::toObjectSpace(const Box &b) const {
|
||||
return inverse().toWorldSpace(b);
|
||||
}
|
||||
|
||||
|
||||
Box CoordinateFrame::toObjectSpace(const AABox& b) const {
|
||||
return toObjectSpace(Box(b));
|
||||
}
|
||||
|
||||
|
||||
CoordinateFrame::CoordinateFrame(class BinaryInput& b) : rotation(Matrix3::zero()) {
|
||||
deserialize(b);
|
||||
}
|
||||
|
||||
|
||||
void CoordinateFrame::deserialize(class BinaryInput& b) {
|
||||
rotation.deserialize(b);
|
||||
translation.deserialize(b);
|
||||
}
|
||||
|
||||
|
||||
void CoordinateFrame::serialize(class BinaryOutput& b) const {
|
||||
rotation.serialize(b);
|
||||
translation.serialize(b);
|
||||
}
|
||||
|
||||
|
||||
Sphere CoordinateFrame::toWorldSpace(const Sphere &b) const {
|
||||
return Sphere(pointToWorldSpace(b.center), b.radius);
|
||||
}
|
||||
|
||||
|
||||
Sphere CoordinateFrame::toObjectSpace(const Sphere &b) const {
|
||||
return Sphere(pointToObjectSpace(b.center), b.radius);
|
||||
}
|
||||
|
||||
|
||||
Ray CoordinateFrame::toWorldSpace(const Ray& r) const {
|
||||
return Ray::fromOriginAndDirection(pointToWorldSpace(r.origin()), vectorToWorldSpace(r.direction()));
|
||||
}
|
||||
|
||||
|
||||
Ray CoordinateFrame::toObjectSpace(const Ray& r) const {
|
||||
return Ray::fromOriginAndDirection(pointToObjectSpace(r.origin()), vectorToObjectSpace(r.direction()));
|
||||
}
|
||||
|
||||
|
||||
void CoordinateFrame::lookAt(const Vector3 &target) {
|
||||
lookAt(target, Vector3::unitY());
|
||||
}
|
||||
|
||||
|
||||
void CoordinateFrame::lookAt(
|
||||
const Vector3& target,
|
||||
Vector3 up) {
|
||||
|
||||
up = up.direction();
|
||||
|
||||
Vector3 look = (target - translation).direction();
|
||||
if (fabs(look.dot(up)) > .99f) {
|
||||
up = Vector3::unitX();
|
||||
if (fabs(look.dot(up)) > .99f) {
|
||||
up = Vector3::unitY();
|
||||
}
|
||||
}
|
||||
|
||||
up -= look * look.dot(up);
|
||||
up.unitize();
|
||||
|
||||
Vector3 z = -look;
|
||||
Vector3 x = -z.cross(up);
|
||||
x.unitize();
|
||||
|
||||
Vector3 y = z.cross(x);
|
||||
|
||||
rotation.setColumn(0, x);
|
||||
rotation.setColumn(1, y);
|
||||
rotation.setColumn(2, z);
|
||||
}
|
||||
|
||||
|
||||
CoordinateFrame CoordinateFrame::lerp(
|
||||
const CoordinateFrame& other,
|
||||
float alpha) const {
|
||||
|
||||
if (alpha == 1.0f) {
|
||||
return other;
|
||||
} else if (alpha == 0.0f) {
|
||||
return *this;
|
||||
} else {
|
||||
Quat q1 = Quat(this->rotation);
|
||||
Quat q2 = Quat(other.rotation);
|
||||
|
||||
return CoordinateFrame(
|
||||
q1.slerp(q2, alpha).toRotationMatrix(),
|
||||
this->translation * (1 - alpha) + other.translation * alpha);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CoordinateFrame::pointToWorldSpace(const Array<Vector3>& v, Array<Vector3>& vout) const {
|
||||
vout.resize(v.size());
|
||||
|
||||
for (int i = v.size() - 1; i >= 0; --i) {
|
||||
vout[i] = pointToWorldSpace(v[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CoordinateFrame::normalToWorldSpace(const Array<Vector3>& v, Array<Vector3>& vout) const {
|
||||
vout.resize(v.size());
|
||||
|
||||
for (int i = v.size() - 1; i >= 0; --i) {
|
||||
vout[i] = normalToWorldSpace(v[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CoordinateFrame::vectorToWorldSpace(const Array<Vector3>& v, Array<Vector3>& vout) const {
|
||||
vout.resize(v.size());
|
||||
|
||||
for (int i = v.size() - 1; i >= 0; --i) {
|
||||
vout[i] = vectorToWorldSpace(v[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CoordinateFrame::pointToObjectSpace(const Array<Vector3>& v, Array<Vector3>& vout) const {
|
||||
vout.resize(v.size());
|
||||
|
||||
for (int i = v.size() - 1; i >= 0; --i) {
|
||||
vout[i] = pointToObjectSpace(v[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CoordinateFrame::normalToObjectSpace(const Array<Vector3>& v, Array<Vector3>& vout) const {
|
||||
vout.resize(v.size());
|
||||
|
||||
for (int i = v.size() - 1; i >= 0; --i) {
|
||||
vout[i] = normalToObjectSpace(v[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CoordinateFrame::vectorToObjectSpace(const Array<Vector3>& v, Array<Vector3>& vout) const {
|
||||
vout.resize(v.size());
|
||||
|
||||
for (int i = v.size() - 1; i >= 0; --i) {
|
||||
vout[i] = vectorToObjectSpace(v[i]);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
70
externals/g3dlite/Crypto.cpp
vendored
Normal file
70
externals/g3dlite/Crypto.cpp
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
/**
|
||||
@file Crypto.cpp
|
||||
|
||||
@author Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
|
||||
@created 2006-03-28
|
||||
@edited 2006-04-06
|
||||
*/
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/Crypto.h"
|
||||
#include "G3D/g3dmath.h"
|
||||
#include <zlib.h>
|
||||
|
||||
namespace G3D {
|
||||
|
||||
|
||||
int Crypto::smallPrime(int n) {
|
||||
debugAssert(n < numSmallPrimes() && n >= 0);
|
||||
|
||||
// From:
|
||||
// http://primes.utm.edu/lists/small/1000.txt
|
||||
|
||||
static const int table[] = {
|
||||
2, 3, 5, 7, 11, 13, 17, 19, 23, 29,
|
||||
31, 37, 41, 43, 47, 53, 59, 61, 67, 71,
|
||||
73, 79, 83, 89, 97, 101, 103, 107, 109, 113,
|
||||
127, 131, 137, 139, 149, 151, 157, 163, 167, 173,
|
||||
179, 181, 191, 193, 197, 199, 211, 223, 227, 229,
|
||||
233, 239, 241, 251, 257, 263, 269, 271, 277, 281,
|
||||
283, 293, 307, 311, 313, 317, 331, 337, 347, 349,
|
||||
353, 359, 367, 373, 379, 383, 389, 397, 401, 409,
|
||||
419, 421, 431, 433, 439, 443, 449, 457, 461, 463,
|
||||
467, 479, 487, 491, 499, 503, 509, 521, 523, 541,
|
||||
547, 557, 563, 569, 571, 577, 587, 593, 599, 601,
|
||||
607, 613, 617, 619, 631, 641, 643, 647, 653, 659,
|
||||
661, 673, 677, 683, 691, 701, 709, 719, 727, 733,
|
||||
739, 743, 751, 757, 761, 769, 773, 787, 797, 809,
|
||||
811, 821, 823, 827, 829, 839, 853, 857, 859, 863,
|
||||
877, 881, 883, 887, 907, 911, 919, 929, 937, 941,
|
||||
947, 953, 967, 971, 977, 983, 991, 997, 1009, 1013,
|
||||
1019, 1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069,
|
||||
1087, 1091, 1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151,
|
||||
1153, 1163, 1171, 1181, 1187, 1193, 1201, 1213, 1217, 1223,
|
||||
1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283, 1289, 1291,
|
||||
1297, 1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373,
|
||||
1381, 1399, 1409, 1423, 1427, 1429, 1433, 1439, 1447, 1451,
|
||||
1453, 1459, 1471, 1481, 1483, 1487, 1489, 1493, 1499, 1511,
|
||||
1523, 1531, 1543, 1549, 1553, 1559, 1567, 1571, 1579, 1583,
|
||||
1597, 1601, 1607, 1609, 1613, 1619, 1621, 1627, 1637, 1657,
|
||||
1663, 1667, 1669, 1693, 1697, 1699, 1709, 1721, 1723, 1733,
|
||||
1741, 1747, 1753, 1759, 1777, 1783, 1787, 1789, 1801, 1811,
|
||||
1823, 1831, 1847, 1861, 1867, 1871, 1873, 1877, 1879, 1889,
|
||||
1901, 1907, 1913, 1931, 1933, 1949, 1951, 1973, 1979, 1987,
|
||||
1993, 1997, 1999};
|
||||
|
||||
return table[n];
|
||||
}
|
||||
|
||||
|
||||
int Crypto::numSmallPrimes() {
|
||||
return 303;
|
||||
}
|
||||
|
||||
uint32 Crypto::crc32(const void* byte, size_t numBytes) {
|
||||
return ::crc32(::crc32(0, Z_NULL, 0), static_cast<const Bytef *>(byte), numBytes);
|
||||
}
|
||||
|
||||
} // G3D
|
||||
176
externals/g3dlite/Cylinder.cpp
vendored
Normal file
176
externals/g3dlite/Cylinder.cpp
vendored
Normal file
@@ -0,0 +1,176 @@
|
||||
/**
|
||||
@file Cylinder.cpp
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
@created 2003-02-07
|
||||
@edited 2006-02-18
|
||||
|
||||
Copyright 2000-2006, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/Cylinder.h"
|
||||
#include "G3D/BinaryInput.h"
|
||||
#include "G3D/BinaryOutput.h"
|
||||
#include "G3D/LineSegment.h"
|
||||
#include "G3D/CoordinateFrame.h"
|
||||
#include "G3D/Line.h"
|
||||
#include "G3D/AABox.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
Cylinder::Cylinder(class BinaryInput& b) {
|
||||
deserialize(b);
|
||||
}
|
||||
|
||||
|
||||
Cylinder::Cylinder() {
|
||||
}
|
||||
|
||||
|
||||
Cylinder::Cylinder(const Vector3& _p1, const Vector3& _p2, float _r)
|
||||
: p1(_p1), p2(_p2), mRadius(_r) {
|
||||
}
|
||||
|
||||
|
||||
void Cylinder::serialize(class BinaryOutput& b) const {
|
||||
p1.serialize(b);
|
||||
p2.serialize(b);
|
||||
b.writeFloat64(mRadius);
|
||||
}
|
||||
|
||||
|
||||
void Cylinder::deserialize(class BinaryInput& b) {
|
||||
p1.deserialize(b);
|
||||
p2.deserialize(b);
|
||||
mRadius = b.readFloat64();
|
||||
}
|
||||
|
||||
|
||||
Line Cylinder::axis() const {
|
||||
return Line::fromTwoPoints(p1, p2);
|
||||
}
|
||||
|
||||
|
||||
|
||||
float Cylinder::radius() const {
|
||||
return mRadius;
|
||||
}
|
||||
|
||||
|
||||
float Cylinder::volume() const {
|
||||
return
|
||||
(float)pi() * square(mRadius) * (p1 - p2).magnitude();
|
||||
}
|
||||
|
||||
|
||||
float Cylinder::area() const {
|
||||
return
|
||||
// Sides
|
||||
(twoPi() * mRadius) * height() +
|
||||
|
||||
// Caps
|
||||
twoPi() * square(mRadius);
|
||||
}
|
||||
|
||||
void Cylinder::getBounds(AABox& out) const {
|
||||
Vector3 min = p1.min(p2) - (Vector3(1, 1, 1) * mRadius);
|
||||
Vector3 max = p1.max(p2) + (Vector3(1, 1, 1) * mRadius);
|
||||
out = AABox(min, max);
|
||||
}
|
||||
|
||||
bool Cylinder::contains(const Vector3& p) const {
|
||||
return LineSegment::fromTwoPoints(p1, p2).distanceSquared(p) <= square(mRadius);
|
||||
}
|
||||
|
||||
|
||||
void Cylinder::getReferenceFrame(CoordinateFrame& cframe) const {
|
||||
cframe.translation = center();
|
||||
|
||||
Vector3 Y = (p1 - p2).direction();
|
||||
Vector3 X = (abs(Y.dot(Vector3::unitX())) > 0.9) ? Vector3::unitY() : Vector3::unitX();
|
||||
Vector3 Z = X.cross(Y).direction();
|
||||
X = Y.cross(Z);
|
||||
cframe.rotation.setColumn(0, X);
|
||||
cframe.rotation.setColumn(1, Y);
|
||||
cframe.rotation.setColumn(2, Z);
|
||||
}
|
||||
|
||||
|
||||
void Cylinder::getRandomSurfacePoint(Vector3& p, Vector3& N) const {
|
||||
float h = height();
|
||||
float r = radius();
|
||||
|
||||
// Create a random point on a standard cylinder and then rotate to the global frame.
|
||||
|
||||
// Relative areas (factor of 2PI already taken out)
|
||||
float capRelArea = square(r) / 2.0f;
|
||||
float sideRelArea = r * h;
|
||||
|
||||
float r1 = uniformRandom(0, capRelArea * 2 + sideRelArea);
|
||||
|
||||
if (r1 < capRelArea * 2) {
|
||||
|
||||
// Select a point uniformly at random on a disk
|
||||
// @cite http://mathworld.wolfram.com/DiskPointPicking.html
|
||||
float a = uniformRandom(0, (float)twoPi());
|
||||
float r2 = sqrt(uniformRandom(0, 1)) * r;
|
||||
p.x = cos(a) * r2;
|
||||
p.z = sin(a) * r2;
|
||||
|
||||
N.x = 0;
|
||||
N.z = 0;
|
||||
if (r1 < capRelArea) {
|
||||
// Top
|
||||
p.y = h / 2.0f;
|
||||
N.y = 1;
|
||||
} else {
|
||||
// Bottom
|
||||
p.y = -h / 2.0f;
|
||||
N.y = -1;
|
||||
}
|
||||
} else {
|
||||
// Side
|
||||
float a = uniformRandom(0, (float)twoPi());
|
||||
N.x = cos(a);
|
||||
N.y = 0;
|
||||
N.z = sin(a);
|
||||
p.x = N.x * r;
|
||||
p.z = N.y * r;
|
||||
p.y = uniformRandom(-h / 2.0f, h / 2.0f);
|
||||
}
|
||||
|
||||
// Transform to world space
|
||||
CoordinateFrame cframe;
|
||||
getReferenceFrame(cframe);
|
||||
|
||||
p = cframe.pointToWorldSpace(p);
|
||||
N = cframe.normalToWorldSpace(N);
|
||||
}
|
||||
|
||||
|
||||
Vector3 Cylinder::randomInteriorPoint() const {
|
||||
float h = height();
|
||||
float r = radius();
|
||||
|
||||
// Create a random point in a standard cylinder and then rotate to the global frame.
|
||||
|
||||
// Select a point uniformly at random on a disk
|
||||
// @cite http://mathworld.wolfram.com/DiskPointPicking.html
|
||||
float a = uniformRandom(0, (float)twoPi());
|
||||
float r2 = sqrt(uniformRandom(0, 1)) * r;
|
||||
|
||||
Vector3 p( cos(a) * r2,
|
||||
uniformRandom(-h / 2.0f, h / 2.0f),
|
||||
sin(a) * r2);
|
||||
|
||||
// Transform to world space
|
||||
CoordinateFrame cframe;
|
||||
getReferenceFrame(cframe);
|
||||
|
||||
return cframe.pointToWorldSpace(p);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
89
externals/g3dlite/Line.cpp
vendored
Normal file
89
externals/g3dlite/Line.cpp
vendored
Normal file
@@ -0,0 +1,89 @@
|
||||
/**
|
||||
@file Line.cpp
|
||||
|
||||
Line class
|
||||
|
||||
@maintainer Morgan McGuire, graphics3d.com
|
||||
|
||||
@created 2001-06-02
|
||||
@edited 2006-01-28
|
||||
*/
|
||||
|
||||
#include "G3D/Line.h"
|
||||
#include "G3D/Plane.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
Vector3 Line::intersection(const Plane& plane) const {
|
||||
float d;
|
||||
Vector3 normal = plane.normal();
|
||||
plane.getEquation(normal, d);
|
||||
float rate = _direction.dot(normal);
|
||||
|
||||
if (rate == 0) {
|
||||
|
||||
return Vector3::inf();
|
||||
|
||||
} else {
|
||||
float t = -(d + _point.dot(normal)) / rate;
|
||||
|
||||
return _point + _direction * t;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Line::Line(class BinaryInput& b) {
|
||||
deserialize(b);
|
||||
}
|
||||
|
||||
|
||||
void Line::serialize(class BinaryOutput& b) const {
|
||||
_point.serialize(b);
|
||||
_direction.serialize(b);
|
||||
}
|
||||
|
||||
|
||||
void Line::deserialize(class BinaryInput& b) {
|
||||
_point.deserialize(b);
|
||||
_direction.deserialize(b);
|
||||
}
|
||||
|
||||
|
||||
Vector3 Line::closestPoint(const Vector3& pt) const {
|
||||
float t = _direction.dot(pt - _point);
|
||||
return _point + _direction * t;
|
||||
}
|
||||
|
||||
|
||||
Vector3 Line::point() const {
|
||||
return _point;
|
||||
}
|
||||
|
||||
|
||||
Vector3 Line::direction() const {
|
||||
return _direction;
|
||||
}
|
||||
|
||||
|
||||
Vector3 Line::closestPoint(const Line& B, float& minDist) const {
|
||||
const Vector3& P1 = _point;
|
||||
const Vector3& U1 = _direction;
|
||||
|
||||
Vector3 P2 = B.point();
|
||||
Vector3 U2 = B.direction();
|
||||
|
||||
const Vector3& P21 = P2 - P1;
|
||||
const Vector3& M = U2.cross(U1);
|
||||
float m2 = M.length();
|
||||
|
||||
Vector3 R = P21.cross(M) / m2;
|
||||
|
||||
float t1 = R.dot(U2);
|
||||
|
||||
minDist = abs(P21.dot(M)) / sqrt(m2);
|
||||
|
||||
return P1 + t1 * U1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
236
externals/g3dlite/LineSegment.cpp
vendored
Normal file
236
externals/g3dlite/LineSegment.cpp
vendored
Normal file
@@ -0,0 +1,236 @@
|
||||
/**
|
||||
@file LineSegment.cpp
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
@created 2003-02-08
|
||||
@edited 2008-02-02
|
||||
*/
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/LineSegment.h"
|
||||
#include "G3D/Sphere.h"
|
||||
#include "G3D/debug.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
|
||||
Vector3 LineSegment::closestPoint(const Vector3& p) const {
|
||||
|
||||
// The vector from the end of the capsule to the point in question.
|
||||
Vector3 v(p - _point);
|
||||
|
||||
// Projection of v onto the line segment scaled by
|
||||
// the length of direction.
|
||||
float t = direction.dot(v);
|
||||
|
||||
// Avoid some square roots. Derivation:
|
||||
// t/direction.length() <= direction.length()
|
||||
// t <= direction.squaredLength()
|
||||
|
||||
if ((t >= 0) && (t <= direction.squaredMagnitude())) {
|
||||
|
||||
// The point falls within the segment. Normalize direction,
|
||||
// divide t by the length of direction.
|
||||
return _point + direction * t / direction.squaredMagnitude();
|
||||
|
||||
} else {
|
||||
|
||||
// The point does not fall within the segment; see which end is closer.
|
||||
|
||||
// Distance from 0, squared
|
||||
float d0Squared = v.squaredMagnitude();
|
||||
|
||||
// Distance from 1, squared
|
||||
float d1Squared = (v - direction).squaredMagnitude();
|
||||
|
||||
if (d0Squared < d1Squared) {
|
||||
|
||||
// Point 0 is closer
|
||||
return _point;
|
||||
|
||||
} else {
|
||||
|
||||
// Point 1 is closer
|
||||
return _point + direction;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Vector3 LineSegment::point(int i) const {
|
||||
switch (i) {
|
||||
case 0:
|
||||
return _point;
|
||||
|
||||
case 1:
|
||||
return _point + direction;
|
||||
|
||||
default:
|
||||
debugAssertM(i == 0 || i == 1, "Argument to point must be 0 or 1");
|
||||
return _point;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool LineSegment::intersectsSolidSphere(const class Sphere& s) const {
|
||||
return distanceSquared(s.center) <= square(s.radius);
|
||||
}
|
||||
|
||||
|
||||
LineSegment::LineSegment(class BinaryInput& b) {
|
||||
deserialize(b);
|
||||
}
|
||||
|
||||
|
||||
void LineSegment::serialize(class BinaryOutput& b) const {
|
||||
_point.serialize(b);
|
||||
direction.serialize(b);
|
||||
}
|
||||
|
||||
|
||||
void LineSegment::deserialize(class BinaryInput& b) {
|
||||
_point.deserialize(b);
|
||||
direction.deserialize(b);
|
||||
}
|
||||
|
||||
|
||||
Vector3 LineSegment::randomPoint() const {
|
||||
return _point + uniformRandom(0, 1) * direction;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
LineSegment2D LineSegment2D::fromTwoPoints(const Vector2& p0, const Vector2& p1) {
|
||||
LineSegment2D s;
|
||||
s.m_origin = p0;
|
||||
s.m_direction = p1 - p0;
|
||||
s.m_length = s.m_direction.length();
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
Vector2 LineSegment2D::point(int i) const {
|
||||
debugAssert(i == 0 || i == 1);
|
||||
if (i == 0) {
|
||||
return m_origin;
|
||||
} else {
|
||||
return m_direction + m_origin;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Vector2 LineSegment2D::closestPoint(const Vector2& Q) const {
|
||||
// Two constants that appear in the result
|
||||
const Vector2 k1(m_origin - Q);
|
||||
const Vector2& k2 = m_direction;
|
||||
|
||||
if (fuzzyEq(m_length, 0)) {
|
||||
// This line segment has no length
|
||||
return m_origin;
|
||||
}
|
||||
|
||||
// Time [0, 1] at which we hit the closest point travelling from p0 to p1.
|
||||
// Derivation can be obtained by minimizing the expression
|
||||
// ||P0 + (P1 - P0)t - Q||.
|
||||
const float t = -k1.dot(k2) / (m_length * m_length);
|
||||
|
||||
if (t < 0) {
|
||||
// Clipped to low end point
|
||||
return m_origin;
|
||||
} else if (t > 1) {
|
||||
// Clipped to high end point
|
||||
return m_origin + m_direction;
|
||||
} else {
|
||||
// Subsitute into the line equation to find
|
||||
// the point on the segment.
|
||||
return m_origin + k2 * t;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
float LineSegment2D::distance(const Vector2& p) const {
|
||||
Vector2 closest = closestPoint(p);
|
||||
return (closest - p).length();
|
||||
}
|
||||
|
||||
|
||||
float LineSegment2D::length() const {
|
||||
return m_length;
|
||||
}
|
||||
|
||||
|
||||
Vector2 LineSegment2D::intersection(const LineSegment2D& other) const {
|
||||
|
||||
if ((m_origin == other.m_origin) ||
|
||||
(m_origin == other.m_origin + other.m_direction)) {
|
||||
return m_origin;
|
||||
}
|
||||
|
||||
if (m_origin + m_direction == other.m_origin) {
|
||||
return other.m_origin;
|
||||
}
|
||||
|
||||
// Note: Now that we've checked the endpoints, all other parallel lines can now be assumed
|
||||
// to not intersect (within numerical precision)
|
||||
|
||||
Vector2 dir1 = m_direction;
|
||||
Vector2 dir2 = other.m_direction;
|
||||
Vector2 origin1 = m_origin;
|
||||
Vector2 origin2 = other.m_origin;
|
||||
|
||||
if (dir1.x == 0) {
|
||||
// Avoid an upcoming divide by zero
|
||||
dir1 = dir1.yx();
|
||||
dir2 = dir2.yx();
|
||||
origin1 = origin1.yx();
|
||||
origin2 = origin2.yx();
|
||||
}
|
||||
|
||||
// t1 = ((other.m_origin.x - m_origin.x) + other.m_direction.x * t2) / m_direction.x
|
||||
//
|
||||
// ((other.m_origin.x - m_origin.x) + other.m_direction.x * t2) * m_direction.y / m_direction.x =
|
||||
// (other.m_origin.y - m_origin.y) + other.m_direction.y * t2
|
||||
//
|
||||
// m = m_direction.y / m_direction.x
|
||||
// d = other.m_origin - m_origin
|
||||
//
|
||||
// (d.x + other.m_direction.x * t2) * m = d.y + other.m_direction.y * t2
|
||||
//
|
||||
// d.x * m + other.m_direction.x * m * t2 = d.y + other.m_direction.y * t2
|
||||
//
|
||||
// d.x * m - d.y = (other.m_direction.y - other.m_direction.x * m) * t2
|
||||
//
|
||||
// (d.x * m - d.y) / (other.m_direction.y - other.m_direction.x * m) = t2
|
||||
//
|
||||
|
||||
Vector2 d = origin2 - origin1;
|
||||
float m = dir1.y / dir1.x;
|
||||
|
||||
float t2 = (d.x * m - d.y) / (dir2.y - dir2.x * m);
|
||||
if (! isFinite(t2)) {
|
||||
// Parallel lines: no intersection
|
||||
return Vector2::inf();
|
||||
}
|
||||
|
||||
if ((t2 < 0.0f) || (t2 > 1.0f)) {
|
||||
// Intersection occurs past the end of the line segments
|
||||
return Vector2::inf();
|
||||
}
|
||||
|
||||
float t1 = (d.x + dir2.x * t2) / dir1.x;
|
||||
if ((t1 < 0.0f) || (t1 > 1.0f)) {
|
||||
// Intersection occurs past the end of the line segments
|
||||
return Vector2::inf();
|
||||
}
|
||||
|
||||
// Return the intersection point (computed from non-transposed
|
||||
// variables even if we flipped above)
|
||||
return m_origin + m_direction * t1;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
146
externals/g3dlite/Log.cpp
vendored
Normal file
146
externals/g3dlite/Log.cpp
vendored
Normal file
@@ -0,0 +1,146 @@
|
||||
/**
|
||||
@file Log.cpp
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
@created 2001-08-04
|
||||
@edited 2009-01-15
|
||||
*/
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/Log.h"
|
||||
#include "G3D/format.h"
|
||||
#include "G3D/Array.h"
|
||||
#include "G3D/fileutils.h"
|
||||
#include <time.h>
|
||||
|
||||
#ifdef G3D_WIN32
|
||||
#include <imagehlp.h>
|
||||
#else
|
||||
#include <stdarg.h>
|
||||
#endif
|
||||
|
||||
namespace G3D {
|
||||
|
||||
void logPrintf(const char* fmt, ...) {
|
||||
va_list arg_list;
|
||||
va_start(arg_list, fmt);
|
||||
Log::common()->vprintf(fmt, arg_list);
|
||||
va_end(arg_list);
|
||||
}
|
||||
|
||||
|
||||
void logLazyPrintf(const char* fmt, ...) {
|
||||
va_list arg_list;
|
||||
va_start(arg_list, fmt);
|
||||
Log::common()->lazyvprintf(fmt, arg_list);
|
||||
va_end(arg_list);
|
||||
}
|
||||
|
||||
Log* Log::commonLog = NULL;
|
||||
|
||||
Log::Log(const std::string& filename, int stripFromStackBottom) :
|
||||
stripFromStackBottom(stripFromStackBottom) {
|
||||
|
||||
this->filename = filename;
|
||||
|
||||
logFile = fopen(filename.c_str(), "w");
|
||||
|
||||
if (logFile == NULL) {
|
||||
std::string drive, base, ext;
|
||||
Array<std::string> path;
|
||||
parseFilename(filename, drive, path, base, ext);
|
||||
std::string logName = base + ((ext != "") ? ("." + ext) : "");
|
||||
|
||||
// Write time is greater than 1ms. This may be a network drive.... try another file.
|
||||
#ifdef G3D_WIN32
|
||||
logName = std::string(std::getenv("TEMP")) + logName;
|
||||
#else
|
||||
logName = std::string("/tmp/") + logName;
|
||||
#endif
|
||||
|
||||
logFile = fopen(logName.c_str(), "w");
|
||||
}
|
||||
|
||||
// Use a large buffer (although we flush in logPrintf)
|
||||
setvbuf(logFile, NULL, _IOFBF, 2048);
|
||||
|
||||
fprintf(logFile, "Application Log\n");
|
||||
time_t t;
|
||||
time(&t);
|
||||
fprintf(logFile, "Start: %s\n", ctime(&t));
|
||||
fflush(logFile);
|
||||
|
||||
if (commonLog == NULL) {
|
||||
commonLog = this;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Log::~Log() {
|
||||
section("Shutdown");
|
||||
println("Closing log file");
|
||||
|
||||
// Make sure we don't leave a dangling pointer
|
||||
if (Log::commonLog == this) {
|
||||
Log::commonLog = NULL;
|
||||
}
|
||||
|
||||
fclose(logFile);
|
||||
}
|
||||
|
||||
|
||||
FILE* Log::getFile() const {
|
||||
return logFile;
|
||||
}
|
||||
|
||||
|
||||
Log* Log::common() {
|
||||
if (commonLog == NULL) {
|
||||
commonLog = new Log();
|
||||
}
|
||||
return commonLog;
|
||||
}
|
||||
|
||||
|
||||
std::string Log::getCommonLogFilename() {
|
||||
return common()->filename;
|
||||
}
|
||||
|
||||
|
||||
void Log::section(const std::string& s) {
|
||||
fprintf(logFile, "_____________________________________________________\n");
|
||||
fprintf(logFile, "\n ### %s ###\n\n", s.c_str());
|
||||
}
|
||||
|
||||
|
||||
void __cdecl Log::printf(const char* fmt, ...) {
|
||||
va_list arg_list;
|
||||
va_start(arg_list, fmt);
|
||||
print(vformat(fmt, arg_list));
|
||||
va_end(arg_list);
|
||||
}
|
||||
|
||||
|
||||
void __cdecl Log::vprintf(const char* fmt, va_list argPtr) {
|
||||
vfprintf(logFile, fmt, argPtr);
|
||||
fflush(logFile);
|
||||
}
|
||||
|
||||
|
||||
void __cdecl Log::lazyvprintf(const char* fmt, va_list argPtr) {
|
||||
vfprintf(logFile, fmt, argPtr);
|
||||
}
|
||||
|
||||
|
||||
void Log::print(const std::string& s) {
|
||||
fprintf(logFile, "%s", s.c_str());
|
||||
fflush(logFile);
|
||||
}
|
||||
|
||||
|
||||
void Log::println(const std::string& s) {
|
||||
fprintf(logFile, "%s\n", s.c_str());
|
||||
fflush(logFile);
|
||||
}
|
||||
|
||||
}
|
||||
1927
externals/g3dlite/Matrix3.cpp
vendored
Normal file
1927
externals/g3dlite/Matrix3.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
523
externals/g3dlite/Matrix4.cpp
vendored
Normal file
523
externals/g3dlite/Matrix4.cpp
vendored
Normal file
@@ -0,0 +1,523 @@
|
||||
/**
|
||||
@file Matrix4.cpp
|
||||
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
@created 2003-10-02
|
||||
@edited 2010-01-29
|
||||
*/
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/Matrix4.h"
|
||||
#include "G3D/Matrix3.h"
|
||||
#include "G3D/Vector4.h"
|
||||
#include "G3D/Vector3.h"
|
||||
#include "G3D/BinaryInput.h"
|
||||
#include "G3D/BinaryOutput.h"
|
||||
#include "G3D/CoordinateFrame.h"
|
||||
#include "G3D/Rect2D.h"
|
||||
#include "G3D/Any.h"
|
||||
#include "G3D/stringutils.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
|
||||
Matrix4::Matrix4(const Any& any) {
|
||||
any.verifyName("Matrix4");
|
||||
any.verifyType(Any::ARRAY);
|
||||
|
||||
const std::string& name = toLower(any.name());
|
||||
if (name == "matrix4") {
|
||||
any.verifySize(16);
|
||||
|
||||
for (int r = 0; r < 4; ++r) {
|
||||
for (int c = 0; c < 4; ++c) {
|
||||
elt[r][c] = any[r * 4 + c];
|
||||
}
|
||||
}
|
||||
} else if (name == "matrix4::scale") {
|
||||
if (any.size() == 1) {
|
||||
*this = scale(any[0].number());
|
||||
} else if (any.size() == 3) {
|
||||
*this = scale(any[0], any[1], any[2]);
|
||||
} else {
|
||||
any.verify(false, "Matrix4::scale() takes either 1 or 3 arguments");
|
||||
}
|
||||
} else {
|
||||
any.verify(false, "Expected Matrix4 constructor");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Matrix4::operator Any() const {
|
||||
Any any(Any::ARRAY, "Matrix4");
|
||||
any.resize(16);
|
||||
for (int r = 0; r < 4; ++r) {
|
||||
for (int c = 0; c < 4; ++c) {
|
||||
any[r * 4 + c] = elt[r][c];
|
||||
}
|
||||
}
|
||||
|
||||
return any;
|
||||
}
|
||||
|
||||
const Matrix4& Matrix4::identity() {
|
||||
static Matrix4 m(
|
||||
1, 0, 0, 0,
|
||||
0, 1, 0, 0,
|
||||
0, 0, 1, 0,
|
||||
0, 0, 0, 1);
|
||||
return m;
|
||||
}
|
||||
|
||||
|
||||
const Matrix4& Matrix4::zero() {
|
||||
static Matrix4 m(
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0);
|
||||
return m;
|
||||
}
|
||||
|
||||
|
||||
Matrix4::Matrix4(const class CoordinateFrame& cframe) {
|
||||
for (int r = 0; r < 3; ++r) {
|
||||
for (int c = 0; c < 3; ++c) {
|
||||
elt[r][c] = cframe.rotation[r][c];
|
||||
}
|
||||
elt[r][3] = cframe.translation[r];
|
||||
}
|
||||
elt[3][0] = 0.0f;
|
||||
elt[3][1] = 0.0f;
|
||||
elt[3][2] = 0.0f;
|
||||
elt[3][3] = 1.0f;
|
||||
}
|
||||
|
||||
Matrix4::Matrix4(const Matrix3& upper3x3, const Vector3& lastCol) {
|
||||
for (int r = 0; r < 3; ++r) {
|
||||
for (int c = 0; c < 3; ++c) {
|
||||
elt[r][c] = upper3x3[r][c];
|
||||
}
|
||||
elt[r][3] = lastCol[r];
|
||||
}
|
||||
elt[3][0] = 0.0f;
|
||||
elt[3][1] = 0.0f;
|
||||
elt[3][2] = 0.0f;
|
||||
elt[3][3] = 1.0f;
|
||||
}
|
||||
|
||||
|
||||
Matrix3 Matrix4::upper3x3() const {
|
||||
return Matrix3(elt[0][0], elt[0][1], elt[0][2],
|
||||
elt[1][0], elt[1][1], elt[1][2],
|
||||
elt[2][0], elt[2][1], elt[2][2]);
|
||||
}
|
||||
|
||||
|
||||
Matrix4 Matrix4::orthogonalProjection(
|
||||
const class Rect2D& rect,
|
||||
float nearval,
|
||||
float farval,
|
||||
float upDirection) {
|
||||
return Matrix4::orthogonalProjection(rect.x0(), rect.x1(), rect.y1(), rect.y0(), nearval, farval, upDirection);
|
||||
}
|
||||
|
||||
|
||||
Matrix4 Matrix4::orthogonalProjection(
|
||||
float left,
|
||||
float right,
|
||||
float bottom,
|
||||
float top,
|
||||
float nearval,
|
||||
float farval,
|
||||
float upDirection) {
|
||||
|
||||
// Adapted from Mesa. Note that Microsoft (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/opengl/glfunc03_8qnj.asp)
|
||||
// and Linux (http://www.xfree86.org/current/glOrtho.3.html) have different matrices shown in their documentation.
|
||||
|
||||
float x, y, z;
|
||||
float tx, ty, tz;
|
||||
|
||||
x = 2.0f / (right-left);
|
||||
y = 2.0f / (top-bottom);
|
||||
z = -2.0f / (farval-nearval);
|
||||
tx = -(right+left) / (right-left);
|
||||
ty = -(top+bottom) / (top-bottom);
|
||||
tz = -(farval+nearval) / (farval-nearval);
|
||||
|
||||
y *= upDirection;
|
||||
ty *= upDirection;
|
||||
|
||||
return
|
||||
Matrix4( x , 0.0f, 0.0f, tx,
|
||||
0.0f, y , 0.0f, ty,
|
||||
0.0f, 0.0f, z , tz,
|
||||
0.0f, 0.0f, 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
|
||||
Matrix4 Matrix4::perspectiveProjection(
|
||||
float left,
|
||||
float right,
|
||||
float bottom,
|
||||
float top,
|
||||
float nearval,
|
||||
float farval,
|
||||
float upDirection) {
|
||||
|
||||
float x, y, a, b, c, d;
|
||||
|
||||
x = (2.0f*nearval) / (right-left);
|
||||
y = (2.0f*nearval) / (top-bottom);
|
||||
a = (right+left) / (right-left);
|
||||
b = (top+bottom) / (top-bottom);
|
||||
|
||||
if (farval >= finf()) {
|
||||
// Infinite view frustum
|
||||
c = -1.0f;
|
||||
d = -2.0f * nearval;
|
||||
} else {
|
||||
c = -(farval+nearval) / (farval-nearval);
|
||||
d = -(2.0f*farval*nearval) / (farval-nearval);
|
||||
}
|
||||
|
||||
debugAssertM(abs(upDirection) == 1.0f, "upDirection must be -1 or +1");
|
||||
y *= upDirection;
|
||||
b *= upDirection;
|
||||
|
||||
return Matrix4(
|
||||
x, 0, a, 0,
|
||||
0, y, b, 0,
|
||||
0, 0, c, d,
|
||||
0, 0, -1, 0);
|
||||
}
|
||||
|
||||
|
||||
void Matrix4::getPerspectiveProjectionParameters(
|
||||
float& left,
|
||||
float& right,
|
||||
float& bottom,
|
||||
float& top,
|
||||
float& nearval,
|
||||
float& farval,
|
||||
float upDirection) const {
|
||||
|
||||
debugAssertM(abs(upDirection) == 1.0f, "upDirection must be -1 or +1");
|
||||
|
||||
float x = elt[0][0];
|
||||
float y = elt[1][1] * upDirection;
|
||||
float a = elt[0][2];
|
||||
float b = elt[1][2] * upDirection;
|
||||
float c = elt[2][2];
|
||||
float d = elt[2][3];
|
||||
|
||||
// Verify that this really is a projection matrix
|
||||
debugAssertM(elt[3][2] == -1, "Not a projection matrix");
|
||||
debugAssertM(elt[0][1] == 0, "Not a projection matrix");
|
||||
debugAssertM(elt[0][3] == 0, "Not a projection matrix");
|
||||
debugAssertM(elt[1][3] == 0, "Not a projection matrix");
|
||||
debugAssertM(elt[3][3] == 0, "Not a projection matrix");
|
||||
debugAssertM(elt[1][0] == 0, "Not a projection matrix");
|
||||
debugAssertM(elt[2][0] == 0, "Not a projection matrix");
|
||||
debugAssertM(elt[2][1] == 0, "Not a projection matrix");
|
||||
debugAssertM(elt[3][0] == 0, "Not a projection matrix");
|
||||
debugAssertM(elt[3][1] == 0, "Not a projection matrix");
|
||||
|
||||
if (c == -1) {
|
||||
farval = finf();
|
||||
nearval = -d / 2.0f;
|
||||
} else {
|
||||
nearval = d * ((c - 1.0f) / (c + 1.0f) - 1.0f) / (-2.0f * (c - 1.0f) / (c + 1.0f));
|
||||
farval = nearval * ((c - 1.0f) / (c + 1.0f));
|
||||
}
|
||||
|
||||
|
||||
left = (a - 1.0f) * nearval / x;
|
||||
right = 2.0f * nearval / x + left;
|
||||
|
||||
bottom = (b - 1.0f) * nearval / y;
|
||||
top = 2.0f * nearval / y + bottom;
|
||||
}
|
||||
|
||||
|
||||
Matrix4::Matrix4(
|
||||
float r1c1, float r1c2, float r1c3, float r1c4,
|
||||
float r2c1, float r2c2, float r2c3, float r2c4,
|
||||
float r3c1, float r3c2, float r3c3, float r3c4,
|
||||
float r4c1, float r4c2, float r4c3, float r4c4) {
|
||||
elt[0][0] = r1c1; elt[0][1] = r1c2; elt[0][2] = r1c3; elt[0][3] = r1c4;
|
||||
elt[1][0] = r2c1; elt[1][1] = r2c2; elt[1][2] = r2c3; elt[1][3] = r2c4;
|
||||
elt[2][0] = r3c1; elt[2][1] = r3c2; elt[2][2] = r3c3; elt[2][3] = r3c4;
|
||||
elt[3][0] = r4c1; elt[3][1] = r4c2; elt[3][2] = r4c3; elt[3][3] = r4c4;
|
||||
}
|
||||
|
||||
/**
|
||||
init should be <B>row major</B>.
|
||||
*/
|
||||
Matrix4::Matrix4(const float* init) {
|
||||
for (int r = 0; r < 4; ++r) {
|
||||
for (int c = 0; c < 4; ++c) {
|
||||
elt[r][c] = init[r * 4 + c];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Matrix4::Matrix4(const double* init) {
|
||||
for (int r = 0; r < 4; ++r) {
|
||||
for (int c = 0; c < 4; ++c) {
|
||||
elt[r][c] = (float)init[r * 4 + c];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Matrix4::Matrix4() {
|
||||
for (int r = 0; r < 4; ++r) {
|
||||
for (int c = 0; c < 4; ++c) {
|
||||
elt[r][c] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Matrix4::setRow(int r, const Vector4& v) {
|
||||
for (int c = 0; c < 4; ++c) {
|
||||
elt[r][c] = v[c];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Matrix4::setColumn(int c, const Vector4& v) {
|
||||
for (int r = 0; r < 4; ++r) {
|
||||
elt[r][c] = v[r];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const Vector4& Matrix4::row(int r) const {
|
||||
return reinterpret_cast<const Vector4*>(elt[r])[0];
|
||||
}
|
||||
|
||||
|
||||
Vector4 Matrix4::column(int c) const {
|
||||
Vector4 v;
|
||||
for (int r = 0; r < 4; ++r) {
|
||||
v[r] = elt[r][c];
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
Matrix4 Matrix4::operator*(const Matrix4& other) const {
|
||||
Matrix4 result;
|
||||
for (int r = 0; r < 4; ++r) {
|
||||
for (int c = 0; c < 4; ++c) {
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
result.elt[r][c] += elt[r][i] * other.elt[i][c];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
Matrix4 Matrix4::operator*(const float s) const {
|
||||
Matrix4 result;
|
||||
for (int r = 0; r < 4; ++r) {
|
||||
for (int c = 0; c < 4; ++c) {
|
||||
result.elt[r][c] = elt[r][c] * s;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
Vector3 Matrix4::homoMul(const class Vector3& v, float w) const {
|
||||
Vector4 r = (*this) * Vector4(v, w);
|
||||
return r.xyz() * (1.0f / r.w);
|
||||
}
|
||||
|
||||
|
||||
Vector4 Matrix4::operator*(const Vector4& vector) const {
|
||||
Vector4 result(0,0,0,0);
|
||||
for (int r = 0; r < 4; ++r) {
|
||||
for (int c = 0; c < 4; ++c) {
|
||||
result[r] += elt[r][c] * vector[c];
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
Matrix4 Matrix4::transpose() const {
|
||||
Matrix4 result;
|
||||
for (int r = 0; r < 4; ++r) {
|
||||
for (int c = 0; c < 4; ++c) {
|
||||
result.elt[c][r] = elt[r][c];
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
bool Matrix4::operator!=(const Matrix4& other) const {
|
||||
return ! (*this == other);
|
||||
}
|
||||
|
||||
|
||||
bool Matrix4::operator==(const Matrix4& other) const {
|
||||
|
||||
// If the bit patterns are identical, they must be
|
||||
// the same matrix. If not, they *might* still have
|
||||
// equal elements due to floating point weirdness.
|
||||
if (memcmp(this, &other, sizeof(Matrix4) == 0)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (int r = 0; r < 4; ++r) {
|
||||
for (int c = 0; c < 4; ++c) {
|
||||
if (elt[r][c] != other.elt[r][c]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
float Matrix4::determinant() const {
|
||||
// Determinant is the dot product of the first row and the first row
|
||||
// of cofactors (i.e. the first col of the adjoint matrix)
|
||||
return cofactor().row(0).dot(row(0));
|
||||
}
|
||||
|
||||
|
||||
Matrix4 Matrix4::adjoint() const {
|
||||
return cofactor().transpose();
|
||||
}
|
||||
|
||||
|
||||
Matrix4 Matrix4::inverse() const {
|
||||
// Inverse = adjoint / determinant
|
||||
|
||||
Matrix4 A = adjoint();
|
||||
|
||||
// Determinant is the dot product of the first row and the first row
|
||||
// of cofactors (i.e. the first col of the adjoint matrix)
|
||||
float det = A.column(0).dot(row(0));
|
||||
|
||||
return A * (1.0f / det);
|
||||
}
|
||||
|
||||
|
||||
Matrix4 Matrix4::cofactor() const {
|
||||
Matrix4 out;
|
||||
|
||||
// We'll use i to incrementally compute -1 ^ (r+c)
|
||||
int i = 1;
|
||||
|
||||
for (int r = 0; r < 4; ++r) {
|
||||
for (int c = 0; c < 4; ++c) {
|
||||
// Compute the determinant of the 3x3 submatrix
|
||||
float det = subDeterminant(r, c);
|
||||
out.elt[r][c] = i * det;
|
||||
i = -i;
|
||||
}
|
||||
i = -i;
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
float Matrix4::subDeterminant(int excludeRow, int excludeCol) const {
|
||||
// Compute non-excluded row and column indices
|
||||
int row[3];
|
||||
int col[3];
|
||||
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
row[i] = i;
|
||||
col[i] = i;
|
||||
|
||||
if (i >= excludeRow) {
|
||||
++row[i];
|
||||
}
|
||||
if (i >= excludeCol) {
|
||||
++col[i];
|
||||
}
|
||||
}
|
||||
|
||||
// Compute the first row of cofactors
|
||||
float cofactor00 =
|
||||
elt[row[1]][col[1]] * elt[row[2]][col[2]] -
|
||||
elt[row[1]][col[2]] * elt[row[2]][col[1]];
|
||||
|
||||
float cofactor10 =
|
||||
elt[row[1]][col[2]] * elt[row[2]][col[0]] -
|
||||
elt[row[1]][col[0]] * elt[row[2]][col[2]];
|
||||
|
||||
float cofactor20 =
|
||||
elt[row[1]][col[0]] * elt[row[2]][col[1]] -
|
||||
elt[row[1]][col[1]] * elt[row[2]][col[0]];
|
||||
|
||||
// Product of the first row and the cofactors along the first row
|
||||
return
|
||||
elt[row[0]][col[0]] * cofactor00 +
|
||||
elt[row[0]][col[1]] * cofactor10 +
|
||||
elt[row[0]][col[2]] * cofactor20;
|
||||
}
|
||||
|
||||
|
||||
CoordinateFrame Matrix4::approxCoordinateFrame() const {
|
||||
CoordinateFrame cframe;
|
||||
|
||||
for (int r = 0; r < 3; ++r) {
|
||||
for (int c = 0; c < 3; ++c) {
|
||||
cframe.rotation[r][c] = elt[r][c];
|
||||
}
|
||||
cframe.translation[r] = elt[r][3];
|
||||
}
|
||||
|
||||
// Ensure that the rotation matrix is orthonormal
|
||||
cframe.rotation.orthonormalize();
|
||||
|
||||
return cframe;
|
||||
}
|
||||
|
||||
|
||||
void Matrix4::serialize(class BinaryOutput& b) const {
|
||||
for (int r = 0; r < 4; ++r) {
|
||||
for (int c = 0; c < 4; ++c) {
|
||||
b.writeFloat32(elt[r][c]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Matrix4::deserialize(class BinaryInput& b) {
|
||||
for (int r = 0; r < 4; ++r) {
|
||||
for (int c = 0; c < 4; ++c) {
|
||||
elt[r][c] = b.readFloat32();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string Matrix4::toString() const {
|
||||
return G3D::format("[%g, %g, %g, %g; %g, %g, %g, %g; %g, %g, %g, %g; %g, %g, %g, %g]",
|
||||
elt[0][0], elt[0][1], elt[0][2], elt[0][3],
|
||||
elt[1][0], elt[1][1], elt[1][2], elt[1][3],
|
||||
elt[2][0], elt[2][1], elt[2][2], elt[2][3],
|
||||
elt[3][0], elt[3][1], elt[3][2], elt[3][3]);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
91
externals/g3dlite/MemoryManager.cpp
vendored
Normal file
91
externals/g3dlite/MemoryManager.cpp
vendored
Normal file
@@ -0,0 +1,91 @@
|
||||
/**
|
||||
@file MemoryManager.cpp
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
@created 2009-04-20
|
||||
@edited 2009-05-29
|
||||
|
||||
Copyright 2000-2009, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
#include "G3D/MemoryManager.h"
|
||||
#include "G3D/System.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
MemoryManager::MemoryManager() {}
|
||||
|
||||
|
||||
void* MemoryManager::alloc(size_t s) {
|
||||
return System::malloc(s);
|
||||
}
|
||||
|
||||
|
||||
void MemoryManager::free(void* ptr) {
|
||||
System::free(ptr);
|
||||
}
|
||||
|
||||
|
||||
bool MemoryManager::isThreadsafe() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
MemoryManager::Ref MemoryManager::create() {
|
||||
static MemoryManager::Ref m = new MemoryManager();
|
||||
return m;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////
|
||||
|
||||
AlignedMemoryManager::AlignedMemoryManager() {}
|
||||
|
||||
|
||||
void* AlignedMemoryManager::alloc(size_t s) {
|
||||
return System::alignedMalloc(s, 16);
|
||||
}
|
||||
|
||||
|
||||
void AlignedMemoryManager::free(void* ptr) {
|
||||
System::alignedFree(ptr);
|
||||
}
|
||||
|
||||
|
||||
bool AlignedMemoryManager::isThreadsafe() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
AlignedMemoryManager::Ref AlignedMemoryManager::create() {
|
||||
static AlignedMemoryManager::Ref m = new AlignedMemoryManager();
|
||||
return m;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////
|
||||
|
||||
CRTMemoryManager::CRTMemoryManager() {}
|
||||
|
||||
|
||||
void* CRTMemoryManager::alloc(size_t s) {
|
||||
return ::malloc(s);
|
||||
}
|
||||
|
||||
|
||||
void CRTMemoryManager::free(void* ptr) {
|
||||
return ::free(ptr);
|
||||
}
|
||||
|
||||
|
||||
bool CRTMemoryManager::isThreadsafe() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
CRTMemoryManager::Ref CRTMemoryManager::create() {
|
||||
static CRTMemoryManager::Ref m = new CRTMemoryManager();
|
||||
return m;
|
||||
}
|
||||
}
|
||||
149
externals/g3dlite/Plane.cpp
vendored
Normal file
149
externals/g3dlite/Plane.cpp
vendored
Normal file
@@ -0,0 +1,149 @@
|
||||
/**
|
||||
@file Plane.cpp
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
@created 2003-02-06
|
||||
@edited 2006-01-29
|
||||
*/
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/Plane.h"
|
||||
#include "G3D/BinaryOutput.h"
|
||||
#include "G3D/BinaryInput.h"
|
||||
#include "G3D/stringutils.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
Plane::Plane(class BinaryInput& b) {
|
||||
deserialize(b);
|
||||
}
|
||||
|
||||
|
||||
void Plane::serialize(class BinaryOutput& b) const {
|
||||
_normal.serialize(b);
|
||||
b.writeFloat64(_distance);
|
||||
}
|
||||
|
||||
|
||||
void Plane::deserialize(class BinaryInput& b) {
|
||||
_normal.deserialize(b);
|
||||
_distance = (float)b.readFloat64();
|
||||
}
|
||||
|
||||
|
||||
Plane::Plane(
|
||||
Vector4 point0,
|
||||
Vector4 point1,
|
||||
Vector4 point2) {
|
||||
|
||||
debugAssertM(
|
||||
point0.w != 0 ||
|
||||
point1.w != 0 ||
|
||||
point2.w != 0,
|
||||
"At least one point must be finite.");
|
||||
|
||||
// Rotate the points around so that the finite points come first.
|
||||
|
||||
while ((point0.w == 0) &&
|
||||
((point1.w == 0) || (point2.w != 0))) {
|
||||
Vector4 temp = point0;
|
||||
point0 = point1;
|
||||
point1 = point2;
|
||||
point2 = temp;
|
||||
}
|
||||
|
||||
Vector3 dir1;
|
||||
Vector3 dir2;
|
||||
|
||||
if (point1.w == 0) {
|
||||
// 1 finite, 2 infinite points; the plane must contain
|
||||
// the direction of the two direcitons
|
||||
dir1 = point1.xyz();
|
||||
dir2 = point2.xyz();
|
||||
} else if (point2.w != 0) {
|
||||
// 3 finite points, the plane must contain the directions
|
||||
// betwseen the points.
|
||||
dir1 = point1.xyz() - point0.xyz();
|
||||
dir2 = point2.xyz() - point0.xyz();
|
||||
} else {
|
||||
// 2 finite, 1 infinite point; the plane must contain
|
||||
// the direction between the first two points and the
|
||||
// direction of the third point.
|
||||
dir1 = point1.xyz() - point0.xyz();
|
||||
dir2 = point2.xyz();
|
||||
}
|
||||
|
||||
_normal = dir1.cross(dir2).direction();
|
||||
_distance = _normal.dot(point0.xyz());
|
||||
}
|
||||
|
||||
|
||||
Plane::Plane(
|
||||
const Vector3& point0,
|
||||
const Vector3& point1,
|
||||
const Vector3& point2) {
|
||||
|
||||
_normal = (point1 - point0).cross(point2 - point0).direction();
|
||||
_distance = _normal.dot(point0);
|
||||
}
|
||||
|
||||
|
||||
Plane::Plane(
|
||||
const Vector3& __normal,
|
||||
const Vector3& point) {
|
||||
|
||||
_normal = __normal.direction();
|
||||
_distance = _normal.dot(point);
|
||||
}
|
||||
|
||||
|
||||
Plane Plane::fromEquation(float a, float b, float c, float d) {
|
||||
Vector3 n(a, b, c);
|
||||
float magnitude = n.magnitude();
|
||||
d /= magnitude;
|
||||
n /= magnitude;
|
||||
return Plane(n, -d);
|
||||
}
|
||||
|
||||
|
||||
void Plane::flip() {
|
||||
_normal = -_normal;
|
||||
_distance = -_distance;
|
||||
}
|
||||
|
||||
|
||||
void Plane::getEquation(Vector3& n, float& d) const {
|
||||
double _d;
|
||||
getEquation(n, _d);
|
||||
d = (float)_d;
|
||||
}
|
||||
|
||||
void Plane::getEquation(Vector3& n, double& d) const {
|
||||
n = _normal;
|
||||
d = -_distance;
|
||||
}
|
||||
|
||||
|
||||
void Plane::getEquation(float& a, float& b, float& c, float& d) const {
|
||||
double _a, _b, _c, _d;
|
||||
getEquation(_a, _b, _c, _d);
|
||||
a = (float)_a;
|
||||
b = (float)_b;
|
||||
c = (float)_c;
|
||||
d = (float)_d;
|
||||
}
|
||||
|
||||
void Plane::getEquation(double& a, double& b, double& c, double& d) const {
|
||||
a = _normal.x;
|
||||
b = _normal.y;
|
||||
c = _normal.z;
|
||||
d = -_distance;
|
||||
}
|
||||
|
||||
|
||||
std::string Plane::toString() const {
|
||||
return format("Plane(%g, %g, %g, %g)", _normal.x, _normal.y, _normal.z, _distance);
|
||||
}
|
||||
|
||||
}
|
||||
583
externals/g3dlite/Quat.cpp
vendored
Normal file
583
externals/g3dlite/Quat.cpp
vendored
Normal file
@@ -0,0 +1,583 @@
|
||||
/**
|
||||
@file Quat.cpp
|
||||
|
||||
Quaternion implementation based on Watt & Watt page 363
|
||||
|
||||
@author Morgan McGuire, graphics3d.com
|
||||
|
||||
@created 2002-01-23
|
||||
@edited 2006-01-31
|
||||
*/
|
||||
|
||||
#include "G3D/Quat.h"
|
||||
#include "G3D/BinaryInput.h"
|
||||
#include "G3D/BinaryOutput.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
Quat Quat::fromAxisAngleRotation(
|
||||
const Vector3& axis,
|
||||
float angle) {
|
||||
|
||||
Quat q;
|
||||
|
||||
q.w = cos(angle / 2.0f);
|
||||
q.imag() = axis.direction() * sin(angle / 2.0f);
|
||||
|
||||
return q;
|
||||
}
|
||||
|
||||
|
||||
Quat::Quat(
|
||||
const Matrix3& rot) {
|
||||
|
||||
static const int plus1mod3[] = {1, 2, 0};
|
||||
|
||||
// Find the index of the largest diagonal component
|
||||
// These ? operations hopefully compile to conditional
|
||||
// move instructions instead of branches.
|
||||
int i = (rot[1][1] > rot[0][0]) ? 1 : 0;
|
||||
i = (rot[2][2] > rot[i][i]) ? 2 : i;
|
||||
|
||||
// Find the indices of the other elements
|
||||
int j = plus1mod3[i];
|
||||
int k = plus1mod3[j];
|
||||
|
||||
// Index the elements of the vector part of the quaternion as a float*
|
||||
float* v = (float*)(this);
|
||||
|
||||
// If we attempted to pre-normalize and trusted the matrix to be
|
||||
// perfectly orthonormal, the result would be:
|
||||
//
|
||||
// double c = sqrt((rot[i][i] - (rot[j][j] + rot[k][k])) + 1.0)
|
||||
// v[i] = -c * 0.5
|
||||
// v[j] = -(rot[i][j] + rot[j][i]) * 0.5 / c
|
||||
// v[k] = -(rot[i][k] + rot[k][i]) * 0.5 / c
|
||||
// w = (rot[j][k] - rot[k][j]) * 0.5 / c
|
||||
//
|
||||
// Since we're going to pay the sqrt anyway, we perform a post normalization, which also
|
||||
// fixes any poorly normalized input. Multiply all elements by 2*c in the above, giving:
|
||||
|
||||
// nc2 = -c^2
|
||||
double nc2 = ((rot[j][j] + rot[k][k]) - rot[i][i]) - 1.0;
|
||||
v[i] = nc2;
|
||||
w = (rot[j][k] - rot[k][j]);
|
||||
v[j] = -(rot[i][j] + rot[j][i]);
|
||||
v[k] = -(rot[i][k] + rot[k][i]);
|
||||
|
||||
// We now have the correct result with the wrong magnitude, so normalize it:
|
||||
float s = sqrt(x*x + y*y + z*z + w*w);
|
||||
if (s > 0.00001f) {
|
||||
s = 1.0f / s;
|
||||
x *= s;
|
||||
y *= s;
|
||||
z *= s;
|
||||
w *= s;
|
||||
} else {
|
||||
// The quaternion is nearly zero. Make it 0 0 0 1
|
||||
x = 0.0f;
|
||||
y = 0.0f;
|
||||
z = 0.0f;
|
||||
w = 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Quat::toAxisAngleRotation(
|
||||
Vector3& axis,
|
||||
double& angle) const {
|
||||
|
||||
// Decompose the quaternion into an angle and an axis.
|
||||
|
||||
axis = Vector3(x, y, z);
|
||||
angle = 2 * acos(w);
|
||||
|
||||
float len = sqrt(1.0f - w * w);
|
||||
|
||||
if (fuzzyGt(abs(len), 0.0f)) {
|
||||
axis /= len;
|
||||
}
|
||||
|
||||
// Reduce the range of the angle.
|
||||
|
||||
if (angle < 0) {
|
||||
angle = -angle;
|
||||
axis = -axis;
|
||||
}
|
||||
|
||||
while (angle > twoPi()) {
|
||||
angle -= twoPi();
|
||||
}
|
||||
|
||||
if (abs(angle) > pi()) {
|
||||
angle -= twoPi();
|
||||
}
|
||||
|
||||
// Make the angle positive.
|
||||
|
||||
if (angle < 0.0f) {
|
||||
angle = -angle;
|
||||
axis = -axis;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Matrix3 Quat::toRotationMatrix() const {
|
||||
Matrix3 out = Matrix3::zero();
|
||||
|
||||
toRotationMatrix(out);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
void Quat::toRotationMatrix(
|
||||
Matrix3& rot) const {
|
||||
|
||||
rot = Matrix3(*this);
|
||||
}
|
||||
|
||||
|
||||
Quat Quat::slerp(
|
||||
const Quat& _quat1,
|
||||
float alpha,
|
||||
float threshold) const {
|
||||
|
||||
// From: Game Physics -- David Eberly pg 538-540
|
||||
// Modified to include lerp for small angles, which
|
||||
// is a common practice.
|
||||
|
||||
// See also:
|
||||
// http://number-none.com/product/Understanding%20Slerp,%20Then%20Not%20Using%20It/index.html
|
||||
|
||||
const Quat& quat0 = *this;
|
||||
Quat quat1 = _quat1;
|
||||
|
||||
// angle between quaternion rotations
|
||||
float phi;
|
||||
float cosphi = quat0.dot(quat1);
|
||||
|
||||
|
||||
if (cosphi < 0) {
|
||||
// Change the sign and fix the dot product; we need to
|
||||
// loop the other way to get the shortest path
|
||||
quat1 = -quat1;
|
||||
cosphi = -cosphi;
|
||||
}
|
||||
|
||||
// Using G3D::aCos will clamp the angle to 0 and pi
|
||||
phi = static_cast<float>(G3D::aCos(cosphi));
|
||||
|
||||
if (phi >= threshold) {
|
||||
// For large angles, slerp
|
||||
float scale0, scale1;
|
||||
|
||||
scale0 = sin((1.0f - alpha) * phi);
|
||||
scale1 = sin(alpha * phi);
|
||||
|
||||
return ( (quat0 * scale0) + (quat1 * scale1) ) / sin(phi);
|
||||
} else {
|
||||
// For small angles, linear interpolate
|
||||
return quat0.nlerp(quat1, alpha);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Quat Quat::nlerp(
|
||||
const Quat& quat1,
|
||||
float alpha) const {
|
||||
|
||||
Quat result = (*this) * (1.0f - alpha) + quat1 * alpha;
|
||||
return result / result.magnitude();
|
||||
}
|
||||
|
||||
|
||||
Quat Quat::operator*(const Quat& other) const {
|
||||
|
||||
// Following Watt & Watt, page 360
|
||||
const Vector3& v1 = imag();
|
||||
const Vector3& v2 = other.imag();
|
||||
float s1 = w;
|
||||
float s2 = other.w;
|
||||
|
||||
return Quat(s1*v2 + s2*v1 + v1.cross(v2), s1*s2 - v1.dot(v2));
|
||||
}
|
||||
|
||||
|
||||
// From "Uniform Random Rotations", Ken Shoemake, Graphics Gems III.
|
||||
Quat Quat::unitRandom() {
|
||||
float x0 = uniformRandom();
|
||||
float r1 = sqrtf(1 - x0),
|
||||
r2 = sqrtf(x0);
|
||||
float t1 = (float)G3D::twoPi() * uniformRandom();
|
||||
float t2 = (float)G3D::twoPi() * uniformRandom();
|
||||
float c1 = cosf(t1),
|
||||
s1 = sinf(t1);
|
||||
float c2 = cosf(t2),
|
||||
s2 = sinf(t2);
|
||||
return Quat(s1 * r1, c1 * r1, s2 * r2, c2 * r2);
|
||||
}
|
||||
|
||||
|
||||
void Quat::deserialize(class BinaryInput& b) {
|
||||
x = b.readFloat32();
|
||||
y = b.readFloat32();
|
||||
z = b.readFloat32();
|
||||
w = b.readFloat32();
|
||||
}
|
||||
|
||||
|
||||
void Quat::serialize(class BinaryOutput& b) const {
|
||||
b.writeFloat32(x);
|
||||
b.writeFloat32(y);
|
||||
b.writeFloat32(z);
|
||||
b.writeFloat32(w);
|
||||
}
|
||||
|
||||
|
||||
// 2-char swizzles
|
||||
|
||||
Vector2 Quat::xx() const { return Vector2 (x, x); }
|
||||
Vector2 Quat::yx() const { return Vector2 (y, x); }
|
||||
Vector2 Quat::zx() const { return Vector2 (z, x); }
|
||||
Vector2 Quat::wx() const { return Vector2 (w, x); }
|
||||
Vector2 Quat::xy() const { return Vector2 (x, y); }
|
||||
Vector2 Quat::yy() const { return Vector2 (y, y); }
|
||||
Vector2 Quat::zy() const { return Vector2 (z, y); }
|
||||
Vector2 Quat::wy() const { return Vector2 (w, y); }
|
||||
Vector2 Quat::xz() const { return Vector2 (x, z); }
|
||||
Vector2 Quat::yz() const { return Vector2 (y, z); }
|
||||
Vector2 Quat::zz() const { return Vector2 (z, z); }
|
||||
Vector2 Quat::wz() const { return Vector2 (w, z); }
|
||||
Vector2 Quat::xw() const { return Vector2 (x, w); }
|
||||
Vector2 Quat::yw() const { return Vector2 (y, w); }
|
||||
Vector2 Quat::zw() const { return Vector2 (z, w); }
|
||||
Vector2 Quat::ww() const { return Vector2 (w, w); }
|
||||
|
||||
// 3-char swizzles
|
||||
|
||||
Vector3 Quat::xxx() const { return Vector3 (x, x, x); }
|
||||
Vector3 Quat::yxx() const { return Vector3 (y, x, x); }
|
||||
Vector3 Quat::zxx() const { return Vector3 (z, x, x); }
|
||||
Vector3 Quat::wxx() const { return Vector3 (w, x, x); }
|
||||
Vector3 Quat::xyx() const { return Vector3 (x, y, x); }
|
||||
Vector3 Quat::yyx() const { return Vector3 (y, y, x); }
|
||||
Vector3 Quat::zyx() const { return Vector3 (z, y, x); }
|
||||
Vector3 Quat::wyx() const { return Vector3 (w, y, x); }
|
||||
Vector3 Quat::xzx() const { return Vector3 (x, z, x); }
|
||||
Vector3 Quat::yzx() const { return Vector3 (y, z, x); }
|
||||
Vector3 Quat::zzx() const { return Vector3 (z, z, x); }
|
||||
Vector3 Quat::wzx() const { return Vector3 (w, z, x); }
|
||||
Vector3 Quat::xwx() const { return Vector3 (x, w, x); }
|
||||
Vector3 Quat::ywx() const { return Vector3 (y, w, x); }
|
||||
Vector3 Quat::zwx() const { return Vector3 (z, w, x); }
|
||||
Vector3 Quat::wwx() const { return Vector3 (w, w, x); }
|
||||
Vector3 Quat::xxy() const { return Vector3 (x, x, y); }
|
||||
Vector3 Quat::yxy() const { return Vector3 (y, x, y); }
|
||||
Vector3 Quat::zxy() const { return Vector3 (z, x, y); }
|
||||
Vector3 Quat::wxy() const { return Vector3 (w, x, y); }
|
||||
Vector3 Quat::xyy() const { return Vector3 (x, y, y); }
|
||||
Vector3 Quat::yyy() const { return Vector3 (y, y, y); }
|
||||
Vector3 Quat::zyy() const { return Vector3 (z, y, y); }
|
||||
Vector3 Quat::wyy() const { return Vector3 (w, y, y); }
|
||||
Vector3 Quat::xzy() const { return Vector3 (x, z, y); }
|
||||
Vector3 Quat::yzy() const { return Vector3 (y, z, y); }
|
||||
Vector3 Quat::zzy() const { return Vector3 (z, z, y); }
|
||||
Vector3 Quat::wzy() const { return Vector3 (w, z, y); }
|
||||
Vector3 Quat::xwy() const { return Vector3 (x, w, y); }
|
||||
Vector3 Quat::ywy() const { return Vector3 (y, w, y); }
|
||||
Vector3 Quat::zwy() const { return Vector3 (z, w, y); }
|
||||
Vector3 Quat::wwy() const { return Vector3 (w, w, y); }
|
||||
Vector3 Quat::xxz() const { return Vector3 (x, x, z); }
|
||||
Vector3 Quat::yxz() const { return Vector3 (y, x, z); }
|
||||
Vector3 Quat::zxz() const { return Vector3 (z, x, z); }
|
||||
Vector3 Quat::wxz() const { return Vector3 (w, x, z); }
|
||||
Vector3 Quat::xyz() const { return Vector3 (x, y, z); }
|
||||
Vector3 Quat::yyz() const { return Vector3 (y, y, z); }
|
||||
Vector3 Quat::zyz() const { return Vector3 (z, y, z); }
|
||||
Vector3 Quat::wyz() const { return Vector3 (w, y, z); }
|
||||
Vector3 Quat::xzz() const { return Vector3 (x, z, z); }
|
||||
Vector3 Quat::yzz() const { return Vector3 (y, z, z); }
|
||||
Vector3 Quat::zzz() const { return Vector3 (z, z, z); }
|
||||
Vector3 Quat::wzz() const { return Vector3 (w, z, z); }
|
||||
Vector3 Quat::xwz() const { return Vector3 (x, w, z); }
|
||||
Vector3 Quat::ywz() const { return Vector3 (y, w, z); }
|
||||
Vector3 Quat::zwz() const { return Vector3 (z, w, z); }
|
||||
Vector3 Quat::wwz() const { return Vector3 (w, w, z); }
|
||||
Vector3 Quat::xxw() const { return Vector3 (x, x, w); }
|
||||
Vector3 Quat::yxw() const { return Vector3 (y, x, w); }
|
||||
Vector3 Quat::zxw() const { return Vector3 (z, x, w); }
|
||||
Vector3 Quat::wxw() const { return Vector3 (w, x, w); }
|
||||
Vector3 Quat::xyw() const { return Vector3 (x, y, w); }
|
||||
Vector3 Quat::yyw() const { return Vector3 (y, y, w); }
|
||||
Vector3 Quat::zyw() const { return Vector3 (z, y, w); }
|
||||
Vector3 Quat::wyw() const { return Vector3 (w, y, w); }
|
||||
Vector3 Quat::xzw() const { return Vector3 (x, z, w); }
|
||||
Vector3 Quat::yzw() const { return Vector3 (y, z, w); }
|
||||
Vector3 Quat::zzw() const { return Vector3 (z, z, w); }
|
||||
Vector3 Quat::wzw() const { return Vector3 (w, z, w); }
|
||||
Vector3 Quat::xww() const { return Vector3 (x, w, w); }
|
||||
Vector3 Quat::yww() const { return Vector3 (y, w, w); }
|
||||
Vector3 Quat::zww() const { return Vector3 (z, w, w); }
|
||||
Vector3 Quat::www() const { return Vector3 (w, w, w); }
|
||||
|
||||
// 4-char swizzles
|
||||
|
||||
Vector4 Quat::xxxx() const { return Vector4 (x, x, x, x); }
|
||||
Vector4 Quat::yxxx() const { return Vector4 (y, x, x, x); }
|
||||
Vector4 Quat::zxxx() const { return Vector4 (z, x, x, x); }
|
||||
Vector4 Quat::wxxx() const { return Vector4 (w, x, x, x); }
|
||||
Vector4 Quat::xyxx() const { return Vector4 (x, y, x, x); }
|
||||
Vector4 Quat::yyxx() const { return Vector4 (y, y, x, x); }
|
||||
Vector4 Quat::zyxx() const { return Vector4 (z, y, x, x); }
|
||||
Vector4 Quat::wyxx() const { return Vector4 (w, y, x, x); }
|
||||
Vector4 Quat::xzxx() const { return Vector4 (x, z, x, x); }
|
||||
Vector4 Quat::yzxx() const { return Vector4 (y, z, x, x); }
|
||||
Vector4 Quat::zzxx() const { return Vector4 (z, z, x, x); }
|
||||
Vector4 Quat::wzxx() const { return Vector4 (w, z, x, x); }
|
||||
Vector4 Quat::xwxx() const { return Vector4 (x, w, x, x); }
|
||||
Vector4 Quat::ywxx() const { return Vector4 (y, w, x, x); }
|
||||
Vector4 Quat::zwxx() const { return Vector4 (z, w, x, x); }
|
||||
Vector4 Quat::wwxx() const { return Vector4 (w, w, x, x); }
|
||||
Vector4 Quat::xxyx() const { return Vector4 (x, x, y, x); }
|
||||
Vector4 Quat::yxyx() const { return Vector4 (y, x, y, x); }
|
||||
Vector4 Quat::zxyx() const { return Vector4 (z, x, y, x); }
|
||||
Vector4 Quat::wxyx() const { return Vector4 (w, x, y, x); }
|
||||
Vector4 Quat::xyyx() const { return Vector4 (x, y, y, x); }
|
||||
Vector4 Quat::yyyx() const { return Vector4 (y, y, y, x); }
|
||||
Vector4 Quat::zyyx() const { return Vector4 (z, y, y, x); }
|
||||
Vector4 Quat::wyyx() const { return Vector4 (w, y, y, x); }
|
||||
Vector4 Quat::xzyx() const { return Vector4 (x, z, y, x); }
|
||||
Vector4 Quat::yzyx() const { return Vector4 (y, z, y, x); }
|
||||
Vector4 Quat::zzyx() const { return Vector4 (z, z, y, x); }
|
||||
Vector4 Quat::wzyx() const { return Vector4 (w, z, y, x); }
|
||||
Vector4 Quat::xwyx() const { return Vector4 (x, w, y, x); }
|
||||
Vector4 Quat::ywyx() const { return Vector4 (y, w, y, x); }
|
||||
Vector4 Quat::zwyx() const { return Vector4 (z, w, y, x); }
|
||||
Vector4 Quat::wwyx() const { return Vector4 (w, w, y, x); }
|
||||
Vector4 Quat::xxzx() const { return Vector4 (x, x, z, x); }
|
||||
Vector4 Quat::yxzx() const { return Vector4 (y, x, z, x); }
|
||||
Vector4 Quat::zxzx() const { return Vector4 (z, x, z, x); }
|
||||
Vector4 Quat::wxzx() const { return Vector4 (w, x, z, x); }
|
||||
Vector4 Quat::xyzx() const { return Vector4 (x, y, z, x); }
|
||||
Vector4 Quat::yyzx() const { return Vector4 (y, y, z, x); }
|
||||
Vector4 Quat::zyzx() const { return Vector4 (z, y, z, x); }
|
||||
Vector4 Quat::wyzx() const { return Vector4 (w, y, z, x); }
|
||||
Vector4 Quat::xzzx() const { return Vector4 (x, z, z, x); }
|
||||
Vector4 Quat::yzzx() const { return Vector4 (y, z, z, x); }
|
||||
Vector4 Quat::zzzx() const { return Vector4 (z, z, z, x); }
|
||||
Vector4 Quat::wzzx() const { return Vector4 (w, z, z, x); }
|
||||
Vector4 Quat::xwzx() const { return Vector4 (x, w, z, x); }
|
||||
Vector4 Quat::ywzx() const { return Vector4 (y, w, z, x); }
|
||||
Vector4 Quat::zwzx() const { return Vector4 (z, w, z, x); }
|
||||
Vector4 Quat::wwzx() const { return Vector4 (w, w, z, x); }
|
||||
Vector4 Quat::xxwx() const { return Vector4 (x, x, w, x); }
|
||||
Vector4 Quat::yxwx() const { return Vector4 (y, x, w, x); }
|
||||
Vector4 Quat::zxwx() const { return Vector4 (z, x, w, x); }
|
||||
Vector4 Quat::wxwx() const { return Vector4 (w, x, w, x); }
|
||||
Vector4 Quat::xywx() const { return Vector4 (x, y, w, x); }
|
||||
Vector4 Quat::yywx() const { return Vector4 (y, y, w, x); }
|
||||
Vector4 Quat::zywx() const { return Vector4 (z, y, w, x); }
|
||||
Vector4 Quat::wywx() const { return Vector4 (w, y, w, x); }
|
||||
Vector4 Quat::xzwx() const { return Vector4 (x, z, w, x); }
|
||||
Vector4 Quat::yzwx() const { return Vector4 (y, z, w, x); }
|
||||
Vector4 Quat::zzwx() const { return Vector4 (z, z, w, x); }
|
||||
Vector4 Quat::wzwx() const { return Vector4 (w, z, w, x); }
|
||||
Vector4 Quat::xwwx() const { return Vector4 (x, w, w, x); }
|
||||
Vector4 Quat::ywwx() const { return Vector4 (y, w, w, x); }
|
||||
Vector4 Quat::zwwx() const { return Vector4 (z, w, w, x); }
|
||||
Vector4 Quat::wwwx() const { return Vector4 (w, w, w, x); }
|
||||
Vector4 Quat::xxxy() const { return Vector4 (x, x, x, y); }
|
||||
Vector4 Quat::yxxy() const { return Vector4 (y, x, x, y); }
|
||||
Vector4 Quat::zxxy() const { return Vector4 (z, x, x, y); }
|
||||
Vector4 Quat::wxxy() const { return Vector4 (w, x, x, y); }
|
||||
Vector4 Quat::xyxy() const { return Vector4 (x, y, x, y); }
|
||||
Vector4 Quat::yyxy() const { return Vector4 (y, y, x, y); }
|
||||
Vector4 Quat::zyxy() const { return Vector4 (z, y, x, y); }
|
||||
Vector4 Quat::wyxy() const { return Vector4 (w, y, x, y); }
|
||||
Vector4 Quat::xzxy() const { return Vector4 (x, z, x, y); }
|
||||
Vector4 Quat::yzxy() const { return Vector4 (y, z, x, y); }
|
||||
Vector4 Quat::zzxy() const { return Vector4 (z, z, x, y); }
|
||||
Vector4 Quat::wzxy() const { return Vector4 (w, z, x, y); }
|
||||
Vector4 Quat::xwxy() const { return Vector4 (x, w, x, y); }
|
||||
Vector4 Quat::ywxy() const { return Vector4 (y, w, x, y); }
|
||||
Vector4 Quat::zwxy() const { return Vector4 (z, w, x, y); }
|
||||
Vector4 Quat::wwxy() const { return Vector4 (w, w, x, y); }
|
||||
Vector4 Quat::xxyy() const { return Vector4 (x, x, y, y); }
|
||||
Vector4 Quat::yxyy() const { return Vector4 (y, x, y, y); }
|
||||
Vector4 Quat::zxyy() const { return Vector4 (z, x, y, y); }
|
||||
Vector4 Quat::wxyy() const { return Vector4 (w, x, y, y); }
|
||||
Vector4 Quat::xyyy() const { return Vector4 (x, y, y, y); }
|
||||
Vector4 Quat::yyyy() const { return Vector4 (y, y, y, y); }
|
||||
Vector4 Quat::zyyy() const { return Vector4 (z, y, y, y); }
|
||||
Vector4 Quat::wyyy() const { return Vector4 (w, y, y, y); }
|
||||
Vector4 Quat::xzyy() const { return Vector4 (x, z, y, y); }
|
||||
Vector4 Quat::yzyy() const { return Vector4 (y, z, y, y); }
|
||||
Vector4 Quat::zzyy() const { return Vector4 (z, z, y, y); }
|
||||
Vector4 Quat::wzyy() const { return Vector4 (w, z, y, y); }
|
||||
Vector4 Quat::xwyy() const { return Vector4 (x, w, y, y); }
|
||||
Vector4 Quat::ywyy() const { return Vector4 (y, w, y, y); }
|
||||
Vector4 Quat::zwyy() const { return Vector4 (z, w, y, y); }
|
||||
Vector4 Quat::wwyy() const { return Vector4 (w, w, y, y); }
|
||||
Vector4 Quat::xxzy() const { return Vector4 (x, x, z, y); }
|
||||
Vector4 Quat::yxzy() const { return Vector4 (y, x, z, y); }
|
||||
Vector4 Quat::zxzy() const { return Vector4 (z, x, z, y); }
|
||||
Vector4 Quat::wxzy() const { return Vector4 (w, x, z, y); }
|
||||
Vector4 Quat::xyzy() const { return Vector4 (x, y, z, y); }
|
||||
Vector4 Quat::yyzy() const { return Vector4 (y, y, z, y); }
|
||||
Vector4 Quat::zyzy() const { return Vector4 (z, y, z, y); }
|
||||
Vector4 Quat::wyzy() const { return Vector4 (w, y, z, y); }
|
||||
Vector4 Quat::xzzy() const { return Vector4 (x, z, z, y); }
|
||||
Vector4 Quat::yzzy() const { return Vector4 (y, z, z, y); }
|
||||
Vector4 Quat::zzzy() const { return Vector4 (z, z, z, y); }
|
||||
Vector4 Quat::wzzy() const { return Vector4 (w, z, z, y); }
|
||||
Vector4 Quat::xwzy() const { return Vector4 (x, w, z, y); }
|
||||
Vector4 Quat::ywzy() const { return Vector4 (y, w, z, y); }
|
||||
Vector4 Quat::zwzy() const { return Vector4 (z, w, z, y); }
|
||||
Vector4 Quat::wwzy() const { return Vector4 (w, w, z, y); }
|
||||
Vector4 Quat::xxwy() const { return Vector4 (x, x, w, y); }
|
||||
Vector4 Quat::yxwy() const { return Vector4 (y, x, w, y); }
|
||||
Vector4 Quat::zxwy() const { return Vector4 (z, x, w, y); }
|
||||
Vector4 Quat::wxwy() const { return Vector4 (w, x, w, y); }
|
||||
Vector4 Quat::xywy() const { return Vector4 (x, y, w, y); }
|
||||
Vector4 Quat::yywy() const { return Vector4 (y, y, w, y); }
|
||||
Vector4 Quat::zywy() const { return Vector4 (z, y, w, y); }
|
||||
Vector4 Quat::wywy() const { return Vector4 (w, y, w, y); }
|
||||
Vector4 Quat::xzwy() const { return Vector4 (x, z, w, y); }
|
||||
Vector4 Quat::yzwy() const { return Vector4 (y, z, w, y); }
|
||||
Vector4 Quat::zzwy() const { return Vector4 (z, z, w, y); }
|
||||
Vector4 Quat::wzwy() const { return Vector4 (w, z, w, y); }
|
||||
Vector4 Quat::xwwy() const { return Vector4 (x, w, w, y); }
|
||||
Vector4 Quat::ywwy() const { return Vector4 (y, w, w, y); }
|
||||
Vector4 Quat::zwwy() const { return Vector4 (z, w, w, y); }
|
||||
Vector4 Quat::wwwy() const { return Vector4 (w, w, w, y); }
|
||||
Vector4 Quat::xxxz() const { return Vector4 (x, x, x, z); }
|
||||
Vector4 Quat::yxxz() const { return Vector4 (y, x, x, z); }
|
||||
Vector4 Quat::zxxz() const { return Vector4 (z, x, x, z); }
|
||||
Vector4 Quat::wxxz() const { return Vector4 (w, x, x, z); }
|
||||
Vector4 Quat::xyxz() const { return Vector4 (x, y, x, z); }
|
||||
Vector4 Quat::yyxz() const { return Vector4 (y, y, x, z); }
|
||||
Vector4 Quat::zyxz() const { return Vector4 (z, y, x, z); }
|
||||
Vector4 Quat::wyxz() const { return Vector4 (w, y, x, z); }
|
||||
Vector4 Quat::xzxz() const { return Vector4 (x, z, x, z); }
|
||||
Vector4 Quat::yzxz() const { return Vector4 (y, z, x, z); }
|
||||
Vector4 Quat::zzxz() const { return Vector4 (z, z, x, z); }
|
||||
Vector4 Quat::wzxz() const { return Vector4 (w, z, x, z); }
|
||||
Vector4 Quat::xwxz() const { return Vector4 (x, w, x, z); }
|
||||
Vector4 Quat::ywxz() const { return Vector4 (y, w, x, z); }
|
||||
Vector4 Quat::zwxz() const { return Vector4 (z, w, x, z); }
|
||||
Vector4 Quat::wwxz() const { return Vector4 (w, w, x, z); }
|
||||
Vector4 Quat::xxyz() const { return Vector4 (x, x, y, z); }
|
||||
Vector4 Quat::yxyz() const { return Vector4 (y, x, y, z); }
|
||||
Vector4 Quat::zxyz() const { return Vector4 (z, x, y, z); }
|
||||
Vector4 Quat::wxyz() const { return Vector4 (w, x, y, z); }
|
||||
Vector4 Quat::xyyz() const { return Vector4 (x, y, y, z); }
|
||||
Vector4 Quat::yyyz() const { return Vector4 (y, y, y, z); }
|
||||
Vector4 Quat::zyyz() const { return Vector4 (z, y, y, z); }
|
||||
Vector4 Quat::wyyz() const { return Vector4 (w, y, y, z); }
|
||||
Vector4 Quat::xzyz() const { return Vector4 (x, z, y, z); }
|
||||
Vector4 Quat::yzyz() const { return Vector4 (y, z, y, z); }
|
||||
Vector4 Quat::zzyz() const { return Vector4 (z, z, y, z); }
|
||||
Vector4 Quat::wzyz() const { return Vector4 (w, z, y, z); }
|
||||
Vector4 Quat::xwyz() const { return Vector4 (x, w, y, z); }
|
||||
Vector4 Quat::ywyz() const { return Vector4 (y, w, y, z); }
|
||||
Vector4 Quat::zwyz() const { return Vector4 (z, w, y, z); }
|
||||
Vector4 Quat::wwyz() const { return Vector4 (w, w, y, z); }
|
||||
Vector4 Quat::xxzz() const { return Vector4 (x, x, z, z); }
|
||||
Vector4 Quat::yxzz() const { return Vector4 (y, x, z, z); }
|
||||
Vector4 Quat::zxzz() const { return Vector4 (z, x, z, z); }
|
||||
Vector4 Quat::wxzz() const { return Vector4 (w, x, z, z); }
|
||||
Vector4 Quat::xyzz() const { return Vector4 (x, y, z, z); }
|
||||
Vector4 Quat::yyzz() const { return Vector4 (y, y, z, z); }
|
||||
Vector4 Quat::zyzz() const { return Vector4 (z, y, z, z); }
|
||||
Vector4 Quat::wyzz() const { return Vector4 (w, y, z, z); }
|
||||
Vector4 Quat::xzzz() const { return Vector4 (x, z, z, z); }
|
||||
Vector4 Quat::yzzz() const { return Vector4 (y, z, z, z); }
|
||||
Vector4 Quat::zzzz() const { return Vector4 (z, z, z, z); }
|
||||
Vector4 Quat::wzzz() const { return Vector4 (w, z, z, z); }
|
||||
Vector4 Quat::xwzz() const { return Vector4 (x, w, z, z); }
|
||||
Vector4 Quat::ywzz() const { return Vector4 (y, w, z, z); }
|
||||
Vector4 Quat::zwzz() const { return Vector4 (z, w, z, z); }
|
||||
Vector4 Quat::wwzz() const { return Vector4 (w, w, z, z); }
|
||||
Vector4 Quat::xxwz() const { return Vector4 (x, x, w, z); }
|
||||
Vector4 Quat::yxwz() const { return Vector4 (y, x, w, z); }
|
||||
Vector4 Quat::zxwz() const { return Vector4 (z, x, w, z); }
|
||||
Vector4 Quat::wxwz() const { return Vector4 (w, x, w, z); }
|
||||
Vector4 Quat::xywz() const { return Vector4 (x, y, w, z); }
|
||||
Vector4 Quat::yywz() const { return Vector4 (y, y, w, z); }
|
||||
Vector4 Quat::zywz() const { return Vector4 (z, y, w, z); }
|
||||
Vector4 Quat::wywz() const { return Vector4 (w, y, w, z); }
|
||||
Vector4 Quat::xzwz() const { return Vector4 (x, z, w, z); }
|
||||
Vector4 Quat::yzwz() const { return Vector4 (y, z, w, z); }
|
||||
Vector4 Quat::zzwz() const { return Vector4 (z, z, w, z); }
|
||||
Vector4 Quat::wzwz() const { return Vector4 (w, z, w, z); }
|
||||
Vector4 Quat::xwwz() const { return Vector4 (x, w, w, z); }
|
||||
Vector4 Quat::ywwz() const { return Vector4 (y, w, w, z); }
|
||||
Vector4 Quat::zwwz() const { return Vector4 (z, w, w, z); }
|
||||
Vector4 Quat::wwwz() const { return Vector4 (w, w, w, z); }
|
||||
Vector4 Quat::xxxw() const { return Vector4 (x, x, x, w); }
|
||||
Vector4 Quat::yxxw() const { return Vector4 (y, x, x, w); }
|
||||
Vector4 Quat::zxxw() const { return Vector4 (z, x, x, w); }
|
||||
Vector4 Quat::wxxw() const { return Vector4 (w, x, x, w); }
|
||||
Vector4 Quat::xyxw() const { return Vector4 (x, y, x, w); }
|
||||
Vector4 Quat::yyxw() const { return Vector4 (y, y, x, w); }
|
||||
Vector4 Quat::zyxw() const { return Vector4 (z, y, x, w); }
|
||||
Vector4 Quat::wyxw() const { return Vector4 (w, y, x, w); }
|
||||
Vector4 Quat::xzxw() const { return Vector4 (x, z, x, w); }
|
||||
Vector4 Quat::yzxw() const { return Vector4 (y, z, x, w); }
|
||||
Vector4 Quat::zzxw() const { return Vector4 (z, z, x, w); }
|
||||
Vector4 Quat::wzxw() const { return Vector4 (w, z, x, w); }
|
||||
Vector4 Quat::xwxw() const { return Vector4 (x, w, x, w); }
|
||||
Vector4 Quat::ywxw() const { return Vector4 (y, w, x, w); }
|
||||
Vector4 Quat::zwxw() const { return Vector4 (z, w, x, w); }
|
||||
Vector4 Quat::wwxw() const { return Vector4 (w, w, x, w); }
|
||||
Vector4 Quat::xxyw() const { return Vector4 (x, x, y, w); }
|
||||
Vector4 Quat::yxyw() const { return Vector4 (y, x, y, w); }
|
||||
Vector4 Quat::zxyw() const { return Vector4 (z, x, y, w); }
|
||||
Vector4 Quat::wxyw() const { return Vector4 (w, x, y, w); }
|
||||
Vector4 Quat::xyyw() const { return Vector4 (x, y, y, w); }
|
||||
Vector4 Quat::yyyw() const { return Vector4 (y, y, y, w); }
|
||||
Vector4 Quat::zyyw() const { return Vector4 (z, y, y, w); }
|
||||
Vector4 Quat::wyyw() const { return Vector4 (w, y, y, w); }
|
||||
Vector4 Quat::xzyw() const { return Vector4 (x, z, y, w); }
|
||||
Vector4 Quat::yzyw() const { return Vector4 (y, z, y, w); }
|
||||
Vector4 Quat::zzyw() const { return Vector4 (z, z, y, w); }
|
||||
Vector4 Quat::wzyw() const { return Vector4 (w, z, y, w); }
|
||||
Vector4 Quat::xwyw() const { return Vector4 (x, w, y, w); }
|
||||
Vector4 Quat::ywyw() const { return Vector4 (y, w, y, w); }
|
||||
Vector4 Quat::zwyw() const { return Vector4 (z, w, y, w); }
|
||||
Vector4 Quat::wwyw() const { return Vector4 (w, w, y, w); }
|
||||
Vector4 Quat::xxzw() const { return Vector4 (x, x, z, w); }
|
||||
Vector4 Quat::yxzw() const { return Vector4 (y, x, z, w); }
|
||||
Vector4 Quat::zxzw() const { return Vector4 (z, x, z, w); }
|
||||
Vector4 Quat::wxzw() const { return Vector4 (w, x, z, w); }
|
||||
Vector4 Quat::xyzw() const { return Vector4 (x, y, z, w); }
|
||||
Vector4 Quat::yyzw() const { return Vector4 (y, y, z, w); }
|
||||
Vector4 Quat::zyzw() const { return Vector4 (z, y, z, w); }
|
||||
Vector4 Quat::wyzw() const { return Vector4 (w, y, z, w); }
|
||||
Vector4 Quat::xzzw() const { return Vector4 (x, z, z, w); }
|
||||
Vector4 Quat::yzzw() const { return Vector4 (y, z, z, w); }
|
||||
Vector4 Quat::zzzw() const { return Vector4 (z, z, z, w); }
|
||||
Vector4 Quat::wzzw() const { return Vector4 (w, z, z, w); }
|
||||
Vector4 Quat::xwzw() const { return Vector4 (x, w, z, w); }
|
||||
Vector4 Quat::ywzw() const { return Vector4 (y, w, z, w); }
|
||||
Vector4 Quat::zwzw() const { return Vector4 (z, w, z, w); }
|
||||
Vector4 Quat::wwzw() const { return Vector4 (w, w, z, w); }
|
||||
Vector4 Quat::xxww() const { return Vector4 (x, x, w, w); }
|
||||
Vector4 Quat::yxww() const { return Vector4 (y, x, w, w); }
|
||||
Vector4 Quat::zxww() const { return Vector4 (z, x, w, w); }
|
||||
Vector4 Quat::wxww() const { return Vector4 (w, x, w, w); }
|
||||
Vector4 Quat::xyww() const { return Vector4 (x, y, w, w); }
|
||||
Vector4 Quat::yyww() const { return Vector4 (y, y, w, w); }
|
||||
Vector4 Quat::zyww() const { return Vector4 (z, y, w, w); }
|
||||
Vector4 Quat::wyww() const { return Vector4 (w, y, w, w); }
|
||||
Vector4 Quat::xzww() const { return Vector4 (x, z, w, w); }
|
||||
Vector4 Quat::yzww() const { return Vector4 (y, z, w, w); }
|
||||
Vector4 Quat::zzww() const { return Vector4 (z, z, w, w); }
|
||||
Vector4 Quat::wzww() const { return Vector4 (w, z, w, w); }
|
||||
Vector4 Quat::xwww() const { return Vector4 (x, w, w, w); }
|
||||
Vector4 Quat::ywww() const { return Vector4 (y, w, w, w); }
|
||||
Vector4 Quat::zwww() const { return Vector4 (z, w, w, w); }
|
||||
Vector4 Quat::wwww() const { return Vector4 (w, w, w, w); }
|
||||
}
|
||||
|
||||
212
externals/g3dlite/Random.cpp
vendored
Normal file
212
externals/g3dlite/Random.cpp
vendored
Normal file
@@ -0,0 +1,212 @@
|
||||
/**
|
||||
@file Random.cpp
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
@created 2009-01-02
|
||||
@edited 2009-03-29
|
||||
|
||||
Copyright 2000-2009, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
#include "G3D/Random.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
Random& Random::common() {
|
||||
static Random r;
|
||||
return r;
|
||||
}
|
||||
|
||||
Random::Random(void* x) : state(NULL), m_threadsafe(false) {
|
||||
(void)x;
|
||||
}
|
||||
|
||||
|
||||
Random::Random(uint32 seed, bool threadsafe) : m_threadsafe(threadsafe) {
|
||||
const uint32 X = 1812433253UL;
|
||||
|
||||
state = new uint32[N];
|
||||
state[0] = seed;
|
||||
for (index = 1; index < (int)N; ++index) {
|
||||
state[index] = X * (state[index - 1] ^ (state[index - 1] >> 30)) + index;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Random::~Random() {
|
||||
delete[] state;
|
||||
state = NULL;
|
||||
}
|
||||
|
||||
|
||||
uint32 Random::bits() {
|
||||
// See http://en.wikipedia.org/wiki/Mersenne_twister
|
||||
|
||||
// Make a local copy of the index variable to ensure that it
|
||||
// is not out of bounds
|
||||
int localIndex = index;
|
||||
|
||||
// Automatically checks for index < 0 if corrupted
|
||||
// by unsynchronized threads.
|
||||
if ((unsigned int)localIndex >= (unsigned int)N) {
|
||||
generate();
|
||||
localIndex = 0;
|
||||
}
|
||||
// Increment the global index. It may go out of bounds on
|
||||
// multiple threads, but the above check ensures that the
|
||||
// array index actually used never goes out of bounds.
|
||||
// It doesn't matter if we grab the same array index twice
|
||||
// on two threads, since the distribution of random numbers
|
||||
// will still be uniform.
|
||||
++index;
|
||||
// Return the next random in the sequence
|
||||
uint32 r = state[localIndex];
|
||||
|
||||
// Temper the result
|
||||
r ^= r >> U;
|
||||
r ^= (r << S) & B;
|
||||
r ^= (r << T) & C;
|
||||
r ^= r >> L;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
/** Generate the next N ints, and store them for readback later */
|
||||
void Random::generate() {
|
||||
// Lower R bits
|
||||
static const uint32 LOWER_MASK = (1LU << R) - 1;
|
||||
|
||||
// Upper (32 - R) bits
|
||||
static const uint32 UPPER_MASK = 0xFFFFFFFF << R;
|
||||
static const uint32 mag01[2] = {0UL, (uint32)A};
|
||||
|
||||
if (m_threadsafe) {
|
||||
bool contention = ! lock.lock();
|
||||
if (contention) {
|
||||
// Another thread just generated a set of numbers; no need for
|
||||
// this thread to do it too
|
||||
lock.unlock();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// First N - M
|
||||
for (unsigned int i = 0; i < N - M; ++i) {
|
||||
uint32 x = (state[i] & UPPER_MASK) | (state[i + 1] & LOWER_MASK);
|
||||
state[i] = state[i + M] ^ (x >> 1) ^ mag01[x & 1];
|
||||
}
|
||||
|
||||
// Rest
|
||||
for (unsigned int i = N - M + 1; i < N - 1; ++i) {
|
||||
uint32 x = (state[i] & UPPER_MASK) | (state[i + 1] & LOWER_MASK);
|
||||
state[i] = state[i + (M - N)] ^ (x >> 1) ^ mag01[x & 1];
|
||||
}
|
||||
|
||||
uint32 y = (state[N - 1] & UPPER_MASK) | (state[0] & LOWER_MASK);
|
||||
state[N - 1] = state[M - 1] ^ (y >> 1) ^ mag01[y & 1];
|
||||
index = 0;
|
||||
|
||||
if (m_threadsafe) {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int Random::integer(int low, int high) {
|
||||
int r = iFloor(low + (high - low + 1) * (double)bits() / 0xFFFFFFFFUL);
|
||||
|
||||
// There is a *very small* chance of generating
|
||||
// a number larger than high.
|
||||
if (r > high) {
|
||||
return high;
|
||||
} else {
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
float Random::gaussian(float mean, float stdev) {
|
||||
|
||||
// Using Box-Mueller method from http://www.taygeta.com/random/gaussian.html
|
||||
// Modified to specify standard deviation and mean of distribution
|
||||
float w, x1, x2;
|
||||
|
||||
// Loop until w is less than 1 so that log(w) is negative
|
||||
do {
|
||||
x1 = uniform(-1.0, 1.0);
|
||||
x2 = uniform(-1.0, 1.0);
|
||||
|
||||
w = float(square(x1) + square(x2));
|
||||
} while (w > 1.0f);
|
||||
|
||||
// Transform to gassian distribution
|
||||
// Multiply by sigma (stdev ^ 2) and add mean.
|
||||
return x2 * (float)square(stdev) * sqrtf((-2.0f * logf(w) ) / w) + mean;
|
||||
}
|
||||
|
||||
|
||||
void Random::cosHemi(float& x, float& y, float& z) {
|
||||
const float e1 = uniform();
|
||||
const float e2 = uniform();
|
||||
|
||||
// Jensen's method
|
||||
const float sin_theta = sqrtf(1.0f - e1);
|
||||
const float cos_theta = sqrtf(e1);
|
||||
const float phi = 6.28318531f * e2;
|
||||
|
||||
x = cos(phi) * sin_theta;
|
||||
y = sin(phi) * sin_theta;
|
||||
z = cos_theta;
|
||||
|
||||
// We could also use Malley's method (pbrt p.657), since they are the same cost:
|
||||
//
|
||||
// r = sqrt(e1);
|
||||
// t = 2*pi*e2;
|
||||
// x = cos(t)*r;
|
||||
// y = sin(t)*r;
|
||||
// z = sqrt(1.0 - x*x + y*y);
|
||||
}
|
||||
|
||||
|
||||
void Random::cosPowHemi(const float k, float& x, float& y, float& z) {
|
||||
const float e1 = uniform();
|
||||
const float e2 = uniform();
|
||||
|
||||
const float cos_theta = pow(e1, 1.0f / (k + 1.0f));
|
||||
const float sin_theta = sqrtf(1.0f - square(cos_theta));
|
||||
const float phi = 6.28318531f * e2;
|
||||
|
||||
x = cos(phi) * sin_theta;
|
||||
y = sin(phi) * sin_theta;
|
||||
z = cos_theta;
|
||||
}
|
||||
|
||||
|
||||
void Random::hemi(float& x, float& y, float& z) {
|
||||
sphere(x, y, z);
|
||||
z = fabsf(z);
|
||||
}
|
||||
|
||||
|
||||
void Random::sphere(float& x, float& y, float& z) {
|
||||
// Squared magnitude
|
||||
float m2;
|
||||
|
||||
// Rejection sample
|
||||
do {
|
||||
x = uniform() * 2.0f - 1.0f,
|
||||
y = uniform() * 2.0f - 1.0f,
|
||||
z = uniform() * 2.0f - 1.0f;
|
||||
m2 = x*x + y*y + z*z;
|
||||
} while (m2 >= 1.0f);
|
||||
|
||||
// Divide by magnitude to produce a unit vector
|
||||
float s = rsqrt(m2);
|
||||
x *= s;
|
||||
y *= s;
|
||||
z *= s;
|
||||
}
|
||||
|
||||
} // G3D
|
||||
218
externals/g3dlite/Ray.cpp
vendored
Normal file
218
externals/g3dlite/Ray.cpp
vendored
Normal file
@@ -0,0 +1,218 @@
|
||||
/**
|
||||
@file Ray.cpp
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
@created 2002-07-12
|
||||
@edited 2004-03-19
|
||||
*/
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/Ray.h"
|
||||
#include "G3D/Plane.h"
|
||||
#include "G3D/Sphere.h"
|
||||
#include "G3D/CollisionDetection.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
void Ray::set(const Vector3& origin, const Vector3& direction) {
|
||||
m_origin = origin;
|
||||
m_direction = direction;
|
||||
debugAssert(direction.isUnit());
|
||||
|
||||
m_invDirection = Vector3::one() / direction;
|
||||
|
||||
// ray slope
|
||||
ibyj = m_direction.x * m_invDirection.y;
|
||||
jbyi = m_direction.y * m_invDirection.x;
|
||||
jbyk = m_direction.y * m_invDirection.z;
|
||||
kbyj = m_direction.z * m_invDirection.y;
|
||||
ibyk = m_direction.x * m_invDirection.z;
|
||||
kbyi = m_direction.z * m_invDirection.x;
|
||||
|
||||
// precomputed terms
|
||||
c_xy = m_origin.y - jbyi * m_origin.x;
|
||||
c_xz = m_origin.z - kbyi * m_origin.x;
|
||||
c_yx = m_origin.x - ibyj * m_origin.y;
|
||||
c_yz = m_origin.z - kbyj * m_origin.y;
|
||||
c_zx = m_origin.x - ibyk * m_origin.z;
|
||||
c_zy = m_origin.y - jbyk * m_origin.z;
|
||||
|
||||
//ray slope classification
|
||||
if (m_direction.x < 0) {
|
||||
if (m_direction.y < 0) {
|
||||
if (m_direction.z < 0) {
|
||||
classification = MMM;
|
||||
} else if (m_direction.z > 0) {
|
||||
classification = MMP;
|
||||
} else { //(m_direction.z >= 0)
|
||||
classification = MMO;
|
||||
}
|
||||
} else { //(m_direction.y >= 0)
|
||||
if (m_direction.z < 0) {
|
||||
if (m_direction.y == 0) {
|
||||
classification = MOM;
|
||||
} else {
|
||||
classification = MPM;
|
||||
}
|
||||
} else { //(m_direction.z >= 0)
|
||||
if ((m_direction.y == 0) && (m_direction.z == 0)) {
|
||||
classification = MOO;
|
||||
} else if (m_direction.z == 0) {
|
||||
classification = MPO;
|
||||
} else if (m_direction.y == 0) {
|
||||
classification = MOP;
|
||||
} else {
|
||||
classification = MPP;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else { //(m_direction.x >= 0)
|
||||
if (m_direction.y < 0) {
|
||||
if (m_direction.z < 0) {
|
||||
if (m_direction.x == 0) {
|
||||
classification = OMM;
|
||||
} else {
|
||||
classification = PMM;
|
||||
}
|
||||
} else { //(m_direction.z >= 0)
|
||||
if ((m_direction.x == 0) && (m_direction.z == 0)) {
|
||||
classification = OMO;
|
||||
} else if (m_direction.z == 0) {
|
||||
classification = PMO;
|
||||
} else if (m_direction.x == 0) {
|
||||
classification = OMP;
|
||||
} else {
|
||||
classification = PMP;
|
||||
}
|
||||
}
|
||||
} else { //(m_direction.y >= 0)
|
||||
if (m_direction.z < 0) {
|
||||
if ((m_direction.x == 0) && (m_direction.y == 0)) {
|
||||
classification = OOM;
|
||||
} else if (m_direction.x == 0) {
|
||||
classification = OPM;
|
||||
} else if (m_direction.y == 0) {
|
||||
classification = POM;
|
||||
} else {
|
||||
classification = PPM;
|
||||
}
|
||||
} else { //(m_direction.z > 0)
|
||||
if (m_direction.x == 0) {
|
||||
if (m_direction.y == 0) {
|
||||
classification = OOP;
|
||||
} else if (m_direction.z == 0) {
|
||||
classification = OPO;
|
||||
} else {
|
||||
classification = OPP;
|
||||
}
|
||||
} else {
|
||||
if ((m_direction.y == 0) && (m_direction.z == 0)) {
|
||||
classification = POO;
|
||||
} else if (m_direction.y == 0) {
|
||||
classification = POP;
|
||||
} else if (m_direction.z == 0) {
|
||||
classification = PPO;
|
||||
} else {
|
||||
classification = PPP;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ray::Ray(class BinaryInput& b) {
|
||||
deserialize(b);
|
||||
}
|
||||
|
||||
|
||||
void Ray::serialize(class BinaryOutput& b) const {
|
||||
m_origin.serialize(b);
|
||||
m_direction.serialize(b);
|
||||
}
|
||||
|
||||
|
||||
void Ray::deserialize(class BinaryInput& b) {
|
||||
m_origin.deserialize(b);
|
||||
m_direction.deserialize(b);
|
||||
set(m_origin, m_direction);
|
||||
}
|
||||
|
||||
|
||||
Ray Ray::refract(
|
||||
const Vector3& newOrigin,
|
||||
const Vector3& normal,
|
||||
float iInside,
|
||||
float iOutside) const {
|
||||
|
||||
Vector3 D = m_direction.refractionDirection(normal, iInside, iOutside);
|
||||
return Ray(newOrigin + (m_direction + normal * (float)sign(m_direction.dot(normal))) * 0.001f, D);
|
||||
}
|
||||
|
||||
|
||||
Ray Ray::reflect(
|
||||
const Vector3& newOrigin,
|
||||
const Vector3& normal) const {
|
||||
|
||||
Vector3 D = m_direction.reflectionDirection(normal);
|
||||
return Ray(newOrigin + (D + normal) * 0.001f, D);
|
||||
}
|
||||
|
||||
|
||||
Vector3 Ray::intersection(const Plane& plane) const {
|
||||
float d;
|
||||
Vector3 normal = plane.normal();
|
||||
plane.getEquation(normal, d);
|
||||
float rate = m_direction.dot(normal);
|
||||
|
||||
if (rate >= 0.0f) {
|
||||
return Vector3::inf();
|
||||
} else {
|
||||
float t = -(d + m_origin.dot(normal)) / rate;
|
||||
return m_origin + m_direction * t;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
float Ray::intersectionTime(const class Sphere& sphere, bool solid) const {
|
||||
Vector3 dummy;
|
||||
return CollisionDetection::collisionTimeForMovingPointFixedSphere(
|
||||
m_origin, m_direction, sphere, dummy, dummy, solid);
|
||||
}
|
||||
|
||||
|
||||
float Ray::intersectionTime(const class Plane& plane) const {
|
||||
Vector3 dummy;
|
||||
return CollisionDetection::collisionTimeForMovingPointFixedPlane(
|
||||
m_origin, m_direction, plane, dummy);
|
||||
}
|
||||
|
||||
|
||||
float Ray::intersectionTime(const class Box& box) const {
|
||||
Vector3 dummy;
|
||||
float time = CollisionDetection::collisionTimeForMovingPointFixedBox(
|
||||
m_origin, m_direction, box, dummy);
|
||||
|
||||
if ((time == finf()) && (box.contains(m_origin))) {
|
||||
return 0.0f;
|
||||
} else {
|
||||
return time;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
float Ray::intersectionTime(const class AABox& box) const {
|
||||
Vector3 dummy;
|
||||
bool inside;
|
||||
float time = CollisionDetection::collisionTimeForMovingPointFixedAABox(
|
||||
m_origin, m_direction, box, dummy, inside);
|
||||
|
||||
if ((time == finf()) && inside) {
|
||||
return 0.0f;
|
||||
} else {
|
||||
return time;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
61
externals/g3dlite/ReferenceCount.cpp
vendored
Normal file
61
externals/g3dlite/ReferenceCount.cpp
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
/**
|
||||
@file ReferenceCount.cpp
|
||||
|
||||
Reference Counting Garbage Collector for C++
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
@cite Adapted and extended from Justin Miller's "RGC" class that appeared in BYTE magazine.
|
||||
@cite See also http://www.jelovic.com/articles/cpp_without_memory_errors_slides.htm
|
||||
|
||||
@created 2001-10-23
|
||||
@edited 2009-04-25
|
||||
*/
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/ReferenceCount.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
ReferenceCountedObject::ReferenceCountedObject() :
|
||||
ReferenceCountedObject_refCount(0),
|
||||
ReferenceCountedObject_weakPointer(0) {
|
||||
|
||||
debugAssertM(isValidHeapPointer(this),
|
||||
"Reference counted objects must be allocated on the heap.");
|
||||
}
|
||||
|
||||
void ReferenceCountedObject::ReferenceCountedObject_zeroWeakPointers() {
|
||||
// Tell all of my weak pointers that I'm gone.
|
||||
|
||||
_WeakPtrLinkedList* node = ReferenceCountedObject_weakPointer;
|
||||
|
||||
while (node != NULL) {
|
||||
// Notify the weak pointer that it is going away
|
||||
node->weakPtr->objectCollected();
|
||||
|
||||
// Free the node and advance
|
||||
_WeakPtrLinkedList* tmp = node;
|
||||
node = node->next;
|
||||
delete tmp;
|
||||
}
|
||||
}
|
||||
|
||||
ReferenceCountedObject::~ReferenceCountedObject() {}
|
||||
|
||||
|
||||
ReferenceCountedObject::ReferenceCountedObject(const ReferenceCountedObject& notUsed) :
|
||||
ReferenceCountedObject_refCount(0),
|
||||
ReferenceCountedObject_weakPointer(0) {
|
||||
(void)notUsed;
|
||||
debugAssertM(G3D::isValidHeapPointer(this),
|
||||
"Reference counted objects must be allocated on the heap.");
|
||||
}
|
||||
|
||||
ReferenceCountedObject& ReferenceCountedObject::operator=(const ReferenceCountedObject& other) {
|
||||
(void)other;
|
||||
// Nothing changes when I am assigned; the reference count on
|
||||
// both objects is the same (although my super-class probably
|
||||
// changes).
|
||||
return *this;
|
||||
}
|
||||
|
||||
} // G3D
|
||||
223
externals/g3dlite/Sphere.cpp
vendored
Normal file
223
externals/g3dlite/Sphere.cpp
vendored
Normal file
@@ -0,0 +1,223 @@
|
||||
/**
|
||||
@file Sphere.cpp
|
||||
|
||||
Sphere class
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
@created 2001-04-17
|
||||
@edited 2009-01-20
|
||||
*/
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/Sphere.h"
|
||||
#include "G3D/stringutils.h"
|
||||
#include "G3D/BinaryOutput.h"
|
||||
#include "G3D/BinaryInput.h"
|
||||
#include "G3D/AABox.h"
|
||||
#include "G3D/Plane.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
int32 Sphere::dummy;
|
||||
|
||||
Sphere::Sphere(class BinaryInput& b) {
|
||||
deserialize(b);
|
||||
}
|
||||
|
||||
|
||||
void Sphere::serialize(class BinaryOutput& b) const {
|
||||
center.serialize(b);
|
||||
b.writeFloat64(radius);
|
||||
}
|
||||
|
||||
|
||||
void Sphere::deserialize(class BinaryInput& b) {
|
||||
center.deserialize(b);
|
||||
radius = (float)b.readFloat64();
|
||||
}
|
||||
|
||||
|
||||
std::string Sphere::toString() const {
|
||||
return format("Sphere(<%g, %g, %g>, %g)",
|
||||
center.x, center.y, center.z, radius);
|
||||
}
|
||||
|
||||
|
||||
bool Sphere::contains(const Vector3& point) const {
|
||||
float distance = (center - point).squaredMagnitude();
|
||||
return distance <= square(radius);
|
||||
}
|
||||
|
||||
|
||||
bool Sphere::contains(const Sphere& other) const {
|
||||
float distance = (center - other.center).squaredMagnitude();
|
||||
return (radius >= other.radius) && (distance <= square(radius - other.radius));
|
||||
}
|
||||
|
||||
|
||||
bool Sphere::intersects(const Sphere& other) const {
|
||||
return (other.center - center).length() <= (radius + other.radius);
|
||||
}
|
||||
|
||||
|
||||
void Sphere::merge(const Sphere& other) {
|
||||
if (other.contains(*this)) {
|
||||
*this = other;
|
||||
} else if (! contains(other)) {
|
||||
// The farthest distance is along the axis between the centers, which
|
||||
// must not be colocated since neither contains the other.
|
||||
Vector3 toMe = center - other.center;
|
||||
// Get a point on the axis from each
|
||||
toMe = toMe.direction();
|
||||
const Vector3& A = center + toMe * radius;
|
||||
const Vector3& B = other.center - toMe * other.radius;
|
||||
|
||||
// Now just bound the A->B segment
|
||||
center = (A + B) * 0.5f;
|
||||
radius = (A - B).length();
|
||||
}
|
||||
// (if this contains other, we're done)
|
||||
}
|
||||
|
||||
|
||||
bool Sphere::culledBy(
|
||||
const Array<Plane>& plane,
|
||||
int& cullingPlaneIndex,
|
||||
const uint32 inMask,
|
||||
uint32& outMask) const {
|
||||
|
||||
return culledBy(plane.getCArray(), plane.size(), cullingPlaneIndex, inMask, outMask);
|
||||
}
|
||||
|
||||
|
||||
bool Sphere::culledBy(
|
||||
const Array<Plane>& plane,
|
||||
int& cullingPlaneIndex,
|
||||
const uint32 inMask) const {
|
||||
|
||||
return culledBy(plane.getCArray(), plane.size(), cullingPlaneIndex, inMask);
|
||||
}
|
||||
|
||||
|
||||
bool Sphere::culledBy(
|
||||
const class Plane* plane,
|
||||
int numPlanes,
|
||||
int& cullingPlane,
|
||||
const uint32 _inMask,
|
||||
uint32& childMask) const {
|
||||
|
||||
if (radius == finf()) {
|
||||
// No plane can cull the infinite box
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32 inMask = _inMask;
|
||||
assert(numPlanes < 31);
|
||||
|
||||
childMask = 0;
|
||||
|
||||
// See if there is one plane for which all of the
|
||||
// vertices are in the negative half space.
|
||||
for (int p = 0; p < numPlanes; p++) {
|
||||
|
||||
// Only test planes that are not masked
|
||||
if ((inMask & 1) != 0) {
|
||||
|
||||
bool culledLow = ! plane[p].halfSpaceContainsFinite(center + plane[p].normal() * radius);
|
||||
bool culledHigh = ! plane[p].halfSpaceContainsFinite(center - plane[p].normal() * radius);
|
||||
|
||||
if (culledLow) {
|
||||
// Plane p culled the sphere
|
||||
cullingPlane = p;
|
||||
|
||||
// The caller should not recurse into the children,
|
||||
// since the parent is culled. If they do recurse,
|
||||
// make them only test against this one plane, which
|
||||
// will immediately cull the volume.
|
||||
childMask = 1 << p;
|
||||
return true;
|
||||
|
||||
} else if (culledHigh) {
|
||||
// The bounding volume straddled the plane; we have
|
||||
// to keep testing against this plane
|
||||
childMask |= (1 << p);
|
||||
}
|
||||
}
|
||||
|
||||
// Move on to the next bit.
|
||||
inMask = inMask >> 1;
|
||||
}
|
||||
|
||||
// None of the planes could cull this box
|
||||
cullingPlane = -1;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Sphere::culledBy(
|
||||
const class Plane* plane,
|
||||
int numPlanes,
|
||||
int& cullingPlane,
|
||||
const uint32 _inMask) const {
|
||||
|
||||
uint32 inMask = _inMask;
|
||||
assert(numPlanes < 31);
|
||||
|
||||
// See if there is one plane for which all of the
|
||||
// vertices are in the negative half space.
|
||||
for (int p = 0; p < numPlanes; p++) {
|
||||
|
||||
// Only test planes that are not masked
|
||||
if ((inMask & 1) != 0) {
|
||||
bool culled = ! plane[p].halfSpaceContains(center + plane[p].normal() * radius);
|
||||
if (culled) {
|
||||
// Plane p culled the sphere
|
||||
cullingPlane = p;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Move on to the next bit.
|
||||
inMask = inMask >> 1;
|
||||
}
|
||||
|
||||
// None of the planes could cull this box
|
||||
cullingPlane = -1;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
Vector3 Sphere::randomSurfacePoint() const {
|
||||
return Vector3::random() * radius + center;
|
||||
}
|
||||
|
||||
|
||||
Vector3 Sphere::randomInteriorPoint() const {
|
||||
Vector3 result;
|
||||
do {
|
||||
result = Vector3(uniformRandom(-1, 1),
|
||||
uniformRandom(-1, 1),
|
||||
uniformRandom(-1, 1));
|
||||
} while (result.squaredMagnitude() >= 1.0f);
|
||||
|
||||
return result * radius + center;
|
||||
}
|
||||
|
||||
|
||||
float Sphere::volume() const {
|
||||
return (float)pi() * (4.0f / 3.0f) * powf((float)radius, 3.0f);
|
||||
}
|
||||
|
||||
|
||||
float Sphere::area() const {
|
||||
return (float)pi() * 4.0f * powf((float)radius, 2.0f);
|
||||
}
|
||||
|
||||
|
||||
void Sphere::getBounds(AABox& out) const {
|
||||
Vector3 extent(radius, radius, radius);
|
||||
out = AABox(center - extent, center + extent);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
1746
externals/g3dlite/System.cpp
vendored
Normal file
1746
externals/g3dlite/System.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1136
externals/g3dlite/TextInput.cpp
vendored
Normal file
1136
externals/g3dlite/TextInput.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
452
externals/g3dlite/TextOutput.cpp
vendored
Normal file
452
externals/g3dlite/TextOutput.cpp
vendored
Normal file
@@ -0,0 +1,452 @@
|
||||
/**
|
||||
@file TextOutput.cpp
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
@created 2004-06-21
|
||||
@edited 2006-08-14
|
||||
|
||||
Copyright 2000-2006, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
#include "G3D/TextOutput.h"
|
||||
#include "G3D/Log.h"
|
||||
#include "G3D/fileutils.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
TextOutput::TextOutput(const TextOutput::Settings& opt) :
|
||||
startingNewLine(true),
|
||||
currentColumn(0),
|
||||
inDQuote(false),
|
||||
filename(""),
|
||||
indentLevel(0)
|
||||
{
|
||||
setOptions(opt);
|
||||
}
|
||||
|
||||
|
||||
TextOutput::TextOutput(const std::string& fil, const TextOutput::Settings& opt) :
|
||||
startingNewLine(true),
|
||||
currentColumn(0),
|
||||
inDQuote(false),
|
||||
filename(fil),
|
||||
indentLevel(0)
|
||||
{
|
||||
|
||||
setOptions(opt);
|
||||
}
|
||||
|
||||
|
||||
void TextOutput::setIndentLevel(int i) {
|
||||
indentLevel = i;
|
||||
|
||||
// If there were more pops than pushes, don't let that take us below 0 indent.
|
||||
// Don't ever indent more than the number of columns.
|
||||
indentSpaces =
|
||||
iClamp(option.spacesPerIndent * indentLevel,
|
||||
0,
|
||||
option.numColumns - 1);
|
||||
}
|
||||
|
||||
|
||||
void TextOutput::setOptions(const Settings& _opt) {
|
||||
option = _opt;
|
||||
|
||||
debugAssert(option.numColumns > 1);
|
||||
|
||||
setIndentLevel(indentLevel);
|
||||
|
||||
newline = (option.newlineStyle == Settings::NEWLINE_WINDOWS) ? "\r\n" : "\n";
|
||||
}
|
||||
|
||||
|
||||
void TextOutput::pushIndent() {
|
||||
setIndentLevel(indentLevel + 1);
|
||||
}
|
||||
|
||||
|
||||
void TextOutput::popIndent() {
|
||||
setIndentLevel(indentLevel - 1);
|
||||
}
|
||||
|
||||
|
||||
static std::string escape(const std::string& string) {
|
||||
std::string result = "";
|
||||
|
||||
for (std::string::size_type i = 0; i < string.length(); ++i) {
|
||||
char c = string.at(i);
|
||||
switch (c) {
|
||||
case '\0':
|
||||
result += "\\0";
|
||||
break;
|
||||
|
||||
case '\r':
|
||||
result += "\\r";
|
||||
break;
|
||||
|
||||
case '\n':
|
||||
result += "\\n";
|
||||
break;
|
||||
|
||||
case '\t':
|
||||
result += "\\t";
|
||||
break;
|
||||
|
||||
case '\\':
|
||||
result += "\\\\";
|
||||
break;
|
||||
|
||||
default:
|
||||
result += c;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void TextOutput::writeString(const std::string& string) {
|
||||
// Convert special characters to escape sequences
|
||||
this->printf("\"%s\"", escape(string).c_str());
|
||||
}
|
||||
|
||||
|
||||
void TextOutput::writeBoolean(bool b) {
|
||||
this->printf("%s ", b ? option.trueSymbol.c_str() : option.falseSymbol.c_str());
|
||||
}
|
||||
|
||||
void TextOutput::writeNumber(double n) {
|
||||
this->printf("%f ", n);
|
||||
}
|
||||
|
||||
|
||||
void TextOutput::writeNumber(int n) {
|
||||
this->printf("%d ", n);
|
||||
}
|
||||
|
||||
|
||||
void TextOutput::writeSymbol(const std::string& string) {
|
||||
if (string.size() > 0) {
|
||||
// TODO: check for legal symbols?
|
||||
this->printf("%s ", string.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void TextOutput::writeSymbols(
|
||||
const std::string& a,
|
||||
const std::string& b,
|
||||
const std::string& c,
|
||||
const std::string& d,
|
||||
const std::string& e,
|
||||
const std::string& f) {
|
||||
|
||||
writeSymbol(a);
|
||||
writeSymbol(b);
|
||||
writeSymbol(c);
|
||||
writeSymbol(d);
|
||||
writeSymbol(e);
|
||||
writeSymbol(f);
|
||||
}
|
||||
|
||||
|
||||
void TextOutput::printf(const std::string formatString, ...) {
|
||||
va_list argList;
|
||||
va_start(argList, formatString);
|
||||
this->vprintf(formatString.c_str(), argList);
|
||||
va_end(argList);
|
||||
}
|
||||
|
||||
|
||||
void TextOutput::printf(const char* formatString, ...) {
|
||||
va_list argList;
|
||||
va_start(argList, formatString);
|
||||
this->vprintf(formatString, argList);
|
||||
va_end(argList);
|
||||
}
|
||||
|
||||
|
||||
void TextOutput::convertNewlines(const std::string& in, std::string& out) {
|
||||
// TODO: can be significantly optimized in cases where
|
||||
// single characters are copied in order by walking through
|
||||
// the array and copying substrings as needed.
|
||||
|
||||
if (option.convertNewlines) {
|
||||
out = "";
|
||||
for (uint32 i = 0; i < in.size(); ++i) {
|
||||
if (in[i] == '\n') {
|
||||
// Unix newline
|
||||
out += newline;
|
||||
} else if ((in[i] == '\r') && (i + 1 < in.size()) && (in[i + 1] == '\n')) {
|
||||
// Windows newline
|
||||
out += newline;
|
||||
++i;
|
||||
} else {
|
||||
out += in[i];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
out = in;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void TextOutput::writeNewline() {
|
||||
for (uint32 i = 0; i < newline.size(); ++i) {
|
||||
indentAppend(newline[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void TextOutput::writeNewlines(int numLines) {
|
||||
for (int i = 0; i < numLines; ++i) {
|
||||
writeNewline();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void TextOutput::wordWrapIndentAppend(const std::string& str) {
|
||||
// TODO: keep track of the last space character we saw so we don't
|
||||
// have to always search.
|
||||
|
||||
if ((option.wordWrap == Settings::WRAP_NONE) ||
|
||||
(currentColumn + (int)str.size() <= option.numColumns)) {
|
||||
// No word-wrapping is needed
|
||||
|
||||
// Add one character at a time.
|
||||
// TODO: optimize for strings without newlines to add multiple
|
||||
// characters.
|
||||
for (uint32 i = 0; i < str.size(); ++i) {
|
||||
indentAppend(str[i]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Number of columns to wrap against
|
||||
int cols = option.numColumns - indentSpaces;
|
||||
|
||||
// Copy forward until we exceed the column size,
|
||||
// and then back up and try to insert newlines as needed.
|
||||
for (uint32 i = 0; i < str.size(); ++i) {
|
||||
|
||||
indentAppend(str[i]);
|
||||
if ((str[i] == '\r') && (i + 1 < str.size()) && (str[i + 1] == '\n')) {
|
||||
// \r\n, we need to hit the \n to enter word wrapping.
|
||||
++i;
|
||||
indentAppend(str[i]);
|
||||
}
|
||||
|
||||
if (currentColumn >= cols) {
|
||||
debugAssertM(str[i] != '\n' && str[i] != '\r',
|
||||
"Should never enter word-wrapping on a newline character");
|
||||
|
||||
// True when we're allowed to treat a space as a space.
|
||||
bool unquotedSpace = option.allowWordWrapInsideDoubleQuotes || ! inDQuote;
|
||||
|
||||
// Cases:
|
||||
//
|
||||
// 1. Currently in a series of spaces that ends with a newline
|
||||
// strip all spaces and let the newline
|
||||
// flow through.
|
||||
//
|
||||
// 2. Currently in a series of spaces that does not end with a newline
|
||||
// strip all spaces and replace them with single newline
|
||||
//
|
||||
// 3. Not in a series of spaces
|
||||
// search backwards for a space, then execute case 2.
|
||||
|
||||
// Index of most recent space
|
||||
uint32 lastSpace = data.size() - 1;
|
||||
|
||||
// How far back we had to look for a space
|
||||
uint32 k = 0;
|
||||
uint32 maxLookBackward = currentColumn - indentSpaces;
|
||||
|
||||
// Search backwards (from current character), looking for a space.
|
||||
while ((k < maxLookBackward) &&
|
||||
(lastSpace > 0) &&
|
||||
(! ((data[lastSpace] == ' ') && unquotedSpace))) {
|
||||
--lastSpace;
|
||||
++k;
|
||||
|
||||
if ((data[lastSpace] == '\"') && !option.allowWordWrapInsideDoubleQuotes) {
|
||||
unquotedSpace = ! unquotedSpace;
|
||||
}
|
||||
}
|
||||
|
||||
if (k == maxLookBackward) {
|
||||
// We couldn't find a series of spaces
|
||||
|
||||
if (option.wordWrap == Settings::WRAP_ALWAYS) {
|
||||
// Strip the last character we wrote, force a newline,
|
||||
// and replace the last character;
|
||||
data.pop();
|
||||
writeNewline();
|
||||
indentAppend(str[i]);
|
||||
} else {
|
||||
// Must be Settings::WRAP_WITHOUT_BREAKING
|
||||
//
|
||||
// Don't write the newline; we'll come back to
|
||||
// the word wrap code after writing another character
|
||||
}
|
||||
} else {
|
||||
// We found a series of spaces. If they continue
|
||||
// to the new string, strip spaces off both. Otherwise
|
||||
// strip spaces from data only and insert a newline.
|
||||
|
||||
// Find the start of the spaces. firstSpace is the index of the
|
||||
// first non-space, looking backwards from lastSpace.
|
||||
uint32 firstSpace = lastSpace;
|
||||
while ((k < maxLookBackward) &&
|
||||
(firstSpace > 0) &&
|
||||
(data[firstSpace] == ' ')) {
|
||||
--firstSpace;
|
||||
++k;
|
||||
}
|
||||
|
||||
if (k == maxLookBackward) {
|
||||
++firstSpace;
|
||||
}
|
||||
|
||||
if (lastSpace == (uint32)data.size() - 1) {
|
||||
// Spaces continued up to the new string
|
||||
data.resize(firstSpace + 1);
|
||||
writeNewline();
|
||||
|
||||
// Delete the spaces from the new string
|
||||
while ((i < str.size() - 1) && (str[i + 1] == ' ')) {
|
||||
++i;
|
||||
}
|
||||
} else {
|
||||
// Spaces were somewhere in the middle of the old string.
|
||||
// replace them with a newline.
|
||||
|
||||
// Copy over the characters that should be saved
|
||||
Array<char> temp;
|
||||
for (uint32 j = lastSpace + 1; j < (uint32)data.size(); ++j) {
|
||||
char c = data[j];
|
||||
|
||||
if (c == '\"') {
|
||||
// Undo changes to quoting (they will be re-done
|
||||
// when we paste these characters back on).
|
||||
inDQuote = !inDQuote;
|
||||
}
|
||||
temp.append(c);
|
||||
}
|
||||
|
||||
// Remove those characters and replace with a newline.
|
||||
data.resize(firstSpace + 1);
|
||||
writeNewline();
|
||||
|
||||
// Write them back
|
||||
for (uint32 j = 0; j < (uint32)temp.size(); ++j) {
|
||||
indentAppend(temp[j]);
|
||||
}
|
||||
|
||||
// We are now free to continue adding from the
|
||||
// new string, which may or may not begin with spaces.
|
||||
|
||||
} // if spaces included new string
|
||||
} // if hit indent
|
||||
} // if line exceeded
|
||||
} // iterate over str
|
||||
}
|
||||
|
||||
|
||||
void TextOutput::indentAppend(char c) {
|
||||
|
||||
if (startingNewLine) {
|
||||
for (int j = 0; j < indentSpaces; ++j) {
|
||||
data.push(' ');
|
||||
}
|
||||
startingNewLine = false;
|
||||
currentColumn = indentSpaces;
|
||||
}
|
||||
|
||||
data.push(c);
|
||||
|
||||
// Don't increment the column count on return character
|
||||
// newline is taken care of below.
|
||||
if (c != '\r') {
|
||||
++currentColumn;
|
||||
}
|
||||
|
||||
if (c == '\"') {
|
||||
inDQuote = ! inDQuote;
|
||||
}
|
||||
|
||||
startingNewLine = (c == '\n');
|
||||
if (startingNewLine) {
|
||||
currentColumn = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void TextOutput::vprintf(const char* formatString, va_list argPtr) {
|
||||
std::string str = vformat(formatString, argPtr);
|
||||
|
||||
std::string clean;
|
||||
convertNewlines(str, clean);
|
||||
wordWrapIndentAppend(clean);
|
||||
}
|
||||
|
||||
|
||||
void TextOutput::commit(bool flush) {
|
||||
std::string p = filenamePath(filename);
|
||||
if (! fileExists(p, false)) {
|
||||
createDirectory(p);
|
||||
}
|
||||
|
||||
FILE* f = fopen(filename.c_str(), "wb");
|
||||
debugAssertM(f, "Could not open \"" + filename + "\"");
|
||||
fwrite(data.getCArray(), 1, data.size(), f);
|
||||
if (flush) {
|
||||
fflush(f);
|
||||
}
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
|
||||
void TextOutput::commitString(std::string& out) {
|
||||
// Null terminate
|
||||
data.push('\0');
|
||||
out = data.getCArray();
|
||||
data.pop();
|
||||
}
|
||||
|
||||
|
||||
std::string TextOutput::commitString() {
|
||||
std::string str;
|
||||
commitString(str);
|
||||
return str;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
void serialize(const float& b, TextOutput& to) {
|
||||
to.writeNumber(b);
|
||||
}
|
||||
|
||||
|
||||
void serialize(const bool& b, TextOutput& to) {
|
||||
to.writeSymbol(b ? "true" : "false");
|
||||
}
|
||||
|
||||
|
||||
void serialize(const int& b, TextOutput& to) {
|
||||
to.writeNumber(b);
|
||||
}
|
||||
|
||||
|
||||
void serialize(const uint8& b, TextOutput& to) {
|
||||
to.writeNumber(b);
|
||||
}
|
||||
|
||||
|
||||
void serialize(const double& b, TextOutput& to) {
|
||||
to.writeNumber(b);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
186
externals/g3dlite/Triangle.cpp
vendored
Normal file
186
externals/g3dlite/Triangle.cpp
vendored
Normal file
@@ -0,0 +1,186 @@
|
||||
/**
|
||||
@file Triangle.cpp
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
@created 2001-04-06
|
||||
@edited 2008-12-28
|
||||
|
||||
Copyright 2000-2009, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/Triangle.h"
|
||||
#include "G3D/Plane.h"
|
||||
#include "G3D/BinaryInput.h"
|
||||
#include "G3D/BinaryOutput.h"
|
||||
#include "G3D/debugAssert.h"
|
||||
#include "G3D/AABox.h"
|
||||
#include "G3D/Ray.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
|
||||
void Triangle::init(const Vector3& v0, const Vector3& v1, const Vector3& v2) {
|
||||
|
||||
_plane = Plane(v0, v1, v2);
|
||||
_vertex[0] = v0;
|
||||
_vertex[1] = v1;
|
||||
_vertex[2] = v2;
|
||||
|
||||
static int next[] = {1,2,0};
|
||||
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
const Vector3& e = _vertex[next[i]] - _vertex[i];
|
||||
edgeMagnitude[i] = e.magnitude();
|
||||
|
||||
if (edgeMagnitude[i] == 0) {
|
||||
edgeDirection[i] = Vector3::zero();
|
||||
} else {
|
||||
edgeDirection[i] = e / (float)edgeMagnitude[i];
|
||||
}
|
||||
}
|
||||
|
||||
_edge01 = _vertex[1] - _vertex[0];
|
||||
_edge02 = _vertex[2] - _vertex[0];
|
||||
|
||||
_primaryAxis = _plane.normal().primaryAxis();
|
||||
_area = 0.5f * edgeDirection[0].cross(edgeDirection[2]).magnitude() * (edgeMagnitude[0] * edgeMagnitude[2]);
|
||||
//0.5f * (_vertex[1] - _vertex[0]).cross(_vertex[2] - _vertex[0]).dot(_plane.normal());
|
||||
}
|
||||
|
||||
|
||||
Triangle::Triangle() {
|
||||
init(Vector3::zero(), Vector3::zero(), Vector3::zero());
|
||||
}
|
||||
|
||||
|
||||
Triangle::Triangle(const Vector3& v0, const Vector3& v1, const Vector3& v2) {
|
||||
init(v0, v1, v2);
|
||||
}
|
||||
|
||||
|
||||
Triangle::~Triangle() {
|
||||
}
|
||||
|
||||
|
||||
Triangle::Triangle(class BinaryInput& b) {
|
||||
deserialize(b);
|
||||
}
|
||||
|
||||
|
||||
void Triangle::serialize(class BinaryOutput& b) {
|
||||
_vertex[0].serialize(b);
|
||||
_vertex[1].serialize(b);
|
||||
_vertex[2].serialize(b);
|
||||
}
|
||||
|
||||
|
||||
void Triangle::deserialize(class BinaryInput& b) {
|
||||
_vertex[0].deserialize(b);
|
||||
_vertex[1].deserialize(b);
|
||||
_vertex[2].deserialize(b);
|
||||
init(_vertex[0], _vertex[1], _vertex[2]);
|
||||
}
|
||||
|
||||
|
||||
float Triangle::area() const {
|
||||
return _area;
|
||||
}
|
||||
|
||||
|
||||
const Vector3& Triangle::normal() const {
|
||||
return _plane.normal();
|
||||
}
|
||||
|
||||
|
||||
const Plane& Triangle::plane() const {
|
||||
return _plane;
|
||||
}
|
||||
|
||||
|
||||
Vector3 Triangle::center() const {
|
||||
return (_vertex[0] + _vertex[1] + _vertex[2]) / 3.0;
|
||||
}
|
||||
|
||||
Vector3 Triangle::randomPoint() const {
|
||||
// Choose a random point in the parallelogram
|
||||
|
||||
float s = uniformRandom();
|
||||
float t = uniformRandom();
|
||||
|
||||
if (t > 1.0f - s) {
|
||||
// Outside the triangle; reflect about the
|
||||
// diagonal of the parallelogram
|
||||
t = 1.0f - t;
|
||||
s = 1.0f - s;
|
||||
}
|
||||
|
||||
return _edge01 * s + _edge02 * t + _vertex[0];
|
||||
}
|
||||
|
||||
|
||||
void Triangle::getBounds(AABox& out) const {
|
||||
Vector3 lo = _vertex[0];
|
||||
Vector3 hi = lo;
|
||||
|
||||
for (int i = 1; i < 3; ++i) {
|
||||
lo = lo.min(_vertex[i]);
|
||||
hi = hi.max(_vertex[i]);
|
||||
}
|
||||
|
||||
out = AABox(lo, hi);
|
||||
}
|
||||
|
||||
|
||||
bool Triangle::intersect(const Ray& ray, float& distance, float baryCoord[3]) const {
|
||||
static const float EPS = 1e-5f;
|
||||
|
||||
// See RTR2 ch. 13.7 for the algorithm.
|
||||
|
||||
const Vector3& e1 = edge01();
|
||||
const Vector3& e2 = edge02();
|
||||
const Vector3 p(ray.direction().cross(e2));
|
||||
const float a = e1.dot(p);
|
||||
|
||||
if (abs(a) < EPS) {
|
||||
// Determinant is ill-conditioned; abort early
|
||||
return false;
|
||||
}
|
||||
|
||||
const float f = 1.0f / a;
|
||||
const Vector3 s(ray.origin() - vertex(0));
|
||||
const float u = f * s.dot(p);
|
||||
|
||||
if ((u < 0.0f) || (u > 1.0f)) {
|
||||
// We hit the plane of the m_geometry, but outside the m_geometry
|
||||
return false;
|
||||
}
|
||||
|
||||
const Vector3 q(s.cross(e1));
|
||||
const float v = f * ray.direction().dot(q);
|
||||
|
||||
if ((v < 0.0f) || ((u + v) > 1.0f)) {
|
||||
// We hit the plane of the triangle, but outside the triangle
|
||||
return false;
|
||||
}
|
||||
|
||||
const float t = f * e2.dot(q);
|
||||
|
||||
if ((t > 0.0f) && (t < distance)) {
|
||||
// This is a new hit, closer than the previous one
|
||||
distance = t;
|
||||
|
||||
baryCoord[0] = 1.0 - u - v;
|
||||
baryCoord[1] = u;
|
||||
baryCoord[2] = v;
|
||||
|
||||
return true;
|
||||
} else {
|
||||
// This hit is after the previous hit, so ignore it
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
} // G3D
|
||||
132
externals/g3dlite/UprightFrame.cpp
vendored
Normal file
132
externals/g3dlite/UprightFrame.cpp
vendored
Normal file
@@ -0,0 +1,132 @@
|
||||
/**
|
||||
@file UprightFrame.cpp
|
||||
Box class
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
@created 2007-05-02
|
||||
@edited 2007-05-05
|
||||
*/
|
||||
|
||||
#include "G3D/UprightFrame.h"
|
||||
#include "G3D/BinaryInput.h"
|
||||
#include "G3D/BinaryOutput.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
UprightFrame::UprightFrame(const CoordinateFrame& cframe) {
|
||||
Vector3 look = cframe.lookVector();
|
||||
|
||||
yaw = G3D::pi() + atan2(look.x, look.z);
|
||||
pitch = asin(look.y);
|
||||
|
||||
translation = cframe.translation;
|
||||
}
|
||||
|
||||
|
||||
CoordinateFrame UprightFrame::toCoordinateFrame() const {
|
||||
CoordinateFrame cframe;
|
||||
|
||||
Matrix3 P(Matrix3::fromAxisAngle(Vector3::unitX(), pitch));
|
||||
Matrix3 Y(Matrix3::fromAxisAngle(Vector3::unitY(), yaw));
|
||||
|
||||
cframe.rotation = Y * P;
|
||||
cframe.translation = translation;
|
||||
|
||||
return cframe;
|
||||
}
|
||||
|
||||
|
||||
UprightFrame UprightFrame::operator+(const UprightFrame& other) const {
|
||||
return UprightFrame(translation + other.translation, pitch + other.pitch, yaw + other.yaw);
|
||||
}
|
||||
|
||||
|
||||
UprightFrame UprightFrame::operator*(const float k) const {
|
||||
return UprightFrame(translation * k, pitch * k, yaw * k);
|
||||
}
|
||||
|
||||
|
||||
void UprightFrame::unwrapYaw(UprightFrame* a, int N) {
|
||||
// Use the first point to establish the wrapping convention
|
||||
for (int i = 1; i < N; ++i) {
|
||||
const float prev = a[i - 1].yaw;
|
||||
float& cur = a[i].yaw;
|
||||
|
||||
// No two angles should be more than pi (i.e., 180-degrees) apart.
|
||||
if (abs(cur - prev) > G3D::pi()) {
|
||||
// These angles must have wrapped at zero, causing them
|
||||
// to be interpolated the long way.
|
||||
|
||||
// Find canonical [0, 2pi] versions of these numbers
|
||||
float p = wrap(prev, twoPi());
|
||||
float c = wrap(cur, twoPi());
|
||||
|
||||
// Find the difference -pi < diff < pi between the current and previous values
|
||||
float diff = c - p;
|
||||
if (diff < -G3D::pi()) {
|
||||
diff += twoPi();
|
||||
} else if (diff > G3D::pi()) {
|
||||
diff -= twoPi();
|
||||
}
|
||||
|
||||
// Offset the current from the previous by the difference
|
||||
// between them.
|
||||
cur = prev + diff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void UprightFrame::serialize(class BinaryOutput& b) const {
|
||||
translation.serialize(b);
|
||||
b.writeFloat32(pitch);
|
||||
b.writeFloat32(yaw);
|
||||
}
|
||||
|
||||
|
||||
void UprightFrame::deserialize(class BinaryInput& b) {
|
||||
translation.deserialize(b);
|
||||
pitch = b.readFloat32();
|
||||
yaw = b.readFloat32();
|
||||
}
|
||||
|
||||
|
||||
void UprightSpline::serialize(class BinaryOutput& b) const {
|
||||
b.writeBool8(cyclic);
|
||||
|
||||
b.writeInt32(control.size());
|
||||
for (int i = 0; i < control.size(); ++i) {
|
||||
control[i].serialize(b);
|
||||
}
|
||||
b.writeInt32(time.size());
|
||||
for (int i = 0; i < time.size(); ++i) {
|
||||
b.writeFloat32(time[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void UprightSpline::deserialize(class BinaryInput& b) {
|
||||
cyclic = b.readBool8();
|
||||
|
||||
control.resize(b.readInt32());
|
||||
for (int i = 0; i < control.size(); ++i) {
|
||||
control[i].deserialize(b);
|
||||
}
|
||||
|
||||
if (b.hasMore()) {
|
||||
time.resize(b.readInt32());
|
||||
for (int i = 0; i < time.size(); ++i) {
|
||||
time[i] = b.readFloat32();
|
||||
}
|
||||
debugAssert(time.size() == control.size());
|
||||
} else {
|
||||
// Import legacy path
|
||||
time.resize(control.size());
|
||||
for (int i = 0; i < time.size(); ++i) {
|
||||
time[i] = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
224
externals/g3dlite/Vector2.cpp
vendored
Normal file
224
externals/g3dlite/Vector2.cpp
vendored
Normal file
@@ -0,0 +1,224 @@
|
||||
/**
|
||||
@file Vector2.cpp
|
||||
|
||||
2D vector class, used for texture coordinates primarily.
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
@cite Portions based on Dave Eberly'x Magic Software Library
|
||||
at http://www.magic-software.com
|
||||
|
||||
@created 2001-06-02
|
||||
@edited 2009-11-16
|
||||
*/
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include <stdlib.h>
|
||||
#include "G3D/Vector2.h"
|
||||
#include "G3D/g3dmath.h"
|
||||
#include "G3D/format.h"
|
||||
#include "G3D/BinaryInput.h"
|
||||
#include "G3D/BinaryOutput.h"
|
||||
#include "G3D/TextInput.h"
|
||||
#include "G3D/TextOutput.h"
|
||||
#include "G3D/Any.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
|
||||
Vector2::Vector2(const Any& any) {
|
||||
any.verifyName("Vector2");
|
||||
any.verifyType(Any::TABLE, Any::ARRAY);
|
||||
any.verifySize(2);
|
||||
|
||||
if (any.type() == Any::ARRAY) {
|
||||
x = any[0];
|
||||
y = any[1];
|
||||
} else {
|
||||
// Table
|
||||
x = any["x"];
|
||||
y = any["y"];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Vector2::operator Any() const {
|
||||
Any any(Any::ARRAY, "Vector2");
|
||||
any.append(x, y);
|
||||
return any;
|
||||
}
|
||||
|
||||
|
||||
const Vector2& Vector2::one() {
|
||||
static const Vector2 v(1, 1); return v;
|
||||
}
|
||||
|
||||
|
||||
const Vector2& Vector2::zero() {
|
||||
static Vector2 v(0, 0);
|
||||
return v;
|
||||
}
|
||||
|
||||
const Vector2& Vector2::unitX() {
|
||||
static Vector2 v(1, 0);
|
||||
return v;
|
||||
}
|
||||
|
||||
const Vector2& Vector2::unitY() {
|
||||
static Vector2 v(0, 1);
|
||||
return v;
|
||||
}
|
||||
|
||||
const Vector2& Vector2::inf() {
|
||||
static Vector2 v((float)G3D::finf(), (float)G3D::finf());
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
const Vector2& Vector2::nan() {
|
||||
static Vector2 v((float)G3D::fnan(), (float)G3D::fnan());
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
const Vector2& Vector2::minFinite() {
|
||||
static Vector2 v(-FLT_MAX, -FLT_MAX);
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
const Vector2& Vector2::maxFinite() {
|
||||
static Vector2 v(FLT_MAX, FLT_MAX);
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
size_t Vector2::hashCode() const {
|
||||
unsigned int xhash = (*(int*)(void*)(&x));
|
||||
unsigned int yhash = (*(int*)(void*)(&y));
|
||||
|
||||
return xhash + (yhash * 37);
|
||||
}
|
||||
|
||||
|
||||
Vector2::Vector2(BinaryInput& b) {
|
||||
deserialize(b);
|
||||
}
|
||||
|
||||
|
||||
void Vector2::deserialize(BinaryInput& b) {
|
||||
x = b.readFloat32();
|
||||
y = b.readFloat32();
|
||||
}
|
||||
|
||||
|
||||
void Vector2::serialize(BinaryOutput& b) const {
|
||||
b.writeFloat32(x);
|
||||
b.writeFloat32(y);
|
||||
}
|
||||
|
||||
|
||||
void Vector2::deserialize(TextInput& t) {
|
||||
t.readSymbol("(");
|
||||
x = (float)t.readNumber();
|
||||
t.readSymbol(",");
|
||||
y = (float)t.readNumber();
|
||||
t.readSymbol(")");
|
||||
}
|
||||
|
||||
|
||||
void Vector2::serialize(TextOutput& t) const {
|
||||
t.writeSymbol("(");
|
||||
t.writeNumber(x);
|
||||
t.writeSymbol(",");
|
||||
t.writeNumber(y);
|
||||
t.writeSymbol(")");
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
Vector2 Vector2::random(G3D::Random& r) {
|
||||
Vector2 result;
|
||||
|
||||
do {
|
||||
result = Vector2(r.uniform(-1, 1), r.uniform(-1, 1));
|
||||
|
||||
} while (result.squaredLength() >= 1.0f);
|
||||
|
||||
result.unitize();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
Vector2 Vector2::operator/ (float k) const {
|
||||
return *this * (1.0f / k);
|
||||
}
|
||||
|
||||
Vector2& Vector2::operator/= (float k) {
|
||||
this->x /= k;
|
||||
this->y /= k;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
float Vector2::unitize (float fTolerance) {
|
||||
float fLength = length();
|
||||
|
||||
if (fLength > fTolerance) {
|
||||
float fInvLength = 1.0f / fLength;
|
||||
x *= fInvLength;
|
||||
y *= fInvLength;
|
||||
} else {
|
||||
fLength = 0.0;
|
||||
}
|
||||
|
||||
return fLength;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
std::string Vector2::toString() const {
|
||||
return G3D::format("(%g, %g)", x, y);
|
||||
}
|
||||
|
||||
// 2-char swizzles
|
||||
|
||||
Vector2 Vector2::xx() const { return Vector2 (x, x); }
|
||||
Vector2 Vector2::yx() const { return Vector2 (y, x); }
|
||||
Vector2 Vector2::xy() const { return Vector2 (x, y); }
|
||||
Vector2 Vector2::yy() const { return Vector2 (y, y); }
|
||||
|
||||
// 3-char swizzles
|
||||
|
||||
Vector3 Vector2::xxx() const { return Vector3 (x, x, x); }
|
||||
Vector3 Vector2::yxx() const { return Vector3 (y, x, x); }
|
||||
Vector3 Vector2::xyx() const { return Vector3 (x, y, x); }
|
||||
Vector3 Vector2::yyx() const { return Vector3 (y, y, x); }
|
||||
Vector3 Vector2::xxy() const { return Vector3 (x, x, y); }
|
||||
Vector3 Vector2::yxy() const { return Vector3 (y, x, y); }
|
||||
Vector3 Vector2::xyy() const { return Vector3 (x, y, y); }
|
||||
Vector3 Vector2::yyy() const { return Vector3 (y, y, y); }
|
||||
|
||||
// 4-char swizzles
|
||||
|
||||
Vector4 Vector2::xxxx() const { return Vector4 (x, x, x, x); }
|
||||
Vector4 Vector2::yxxx() const { return Vector4 (y, x, x, x); }
|
||||
Vector4 Vector2::xyxx() const { return Vector4 (x, y, x, x); }
|
||||
Vector4 Vector2::yyxx() const { return Vector4 (y, y, x, x); }
|
||||
Vector4 Vector2::xxyx() const { return Vector4 (x, x, y, x); }
|
||||
Vector4 Vector2::yxyx() const { return Vector4 (y, x, y, x); }
|
||||
Vector4 Vector2::xyyx() const { return Vector4 (x, y, y, x); }
|
||||
Vector4 Vector2::yyyx() const { return Vector4 (y, y, y, x); }
|
||||
Vector4 Vector2::xxxy() const { return Vector4 (x, x, x, y); }
|
||||
Vector4 Vector2::yxxy() const { return Vector4 (y, x, x, y); }
|
||||
Vector4 Vector2::xyxy() const { return Vector4 (x, y, x, y); }
|
||||
Vector4 Vector2::yyxy() const { return Vector4 (y, y, x, y); }
|
||||
Vector4 Vector2::xxyy() const { return Vector4 (x, x, y, y); }
|
||||
Vector4 Vector2::yxyy() const { return Vector4 (y, x, y, y); }
|
||||
Vector4 Vector2::xyyy() const { return Vector4 (x, y, y, y); }
|
||||
Vector4 Vector2::yyyy() const { return Vector4 (y, y, y, y); }
|
||||
|
||||
|
||||
|
||||
} // namespace
|
||||
507
externals/g3dlite/Vector3.cpp
vendored
Normal file
507
externals/g3dlite/Vector3.cpp
vendored
Normal file
@@ -0,0 +1,507 @@
|
||||
/**
|
||||
@file Vector3.cpp
|
||||
|
||||
3D vector class
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
@cite Portions based on Dave Eberly's Magic Software Library at http://www.magic-software.com
|
||||
|
||||
@created 2001-06-02
|
||||
@edited 2009-11-27
|
||||
*/
|
||||
|
||||
#include <limits>
|
||||
#include <stdlib.h>
|
||||
#include "G3D/Vector3.h"
|
||||
#include "G3D/g3dmath.h"
|
||||
#include "G3D/stringutils.h"
|
||||
#include "G3D/BinaryInput.h"
|
||||
#include "G3D/BinaryOutput.h"
|
||||
#include "G3D/TextInput.h"
|
||||
#include "G3D/TextOutput.h"
|
||||
#include "G3D/Vector3int16.h"
|
||||
#include "G3D/Matrix3.h"
|
||||
#include "G3D/Vector2.h"
|
||||
#include "G3D/Color3.h"
|
||||
#include "G3D/Vector4int8.h"
|
||||
#include "G3D/Vector3int32.h"
|
||||
#include "G3D/Any.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
Vector3::Vector3(const Any& any) {
|
||||
any.verifyName("Vector3");
|
||||
any.verifyType(Any::TABLE, Any::ARRAY);
|
||||
any.verifySize(3);
|
||||
|
||||
if (any.type() == Any::ARRAY) {
|
||||
x = any[0];
|
||||
y = any[1];
|
||||
z = any[2];
|
||||
} else {
|
||||
// Table
|
||||
x = any["x"];
|
||||
y = any["y"];
|
||||
z = any["z"];
|
||||
}
|
||||
}
|
||||
|
||||
Vector3::operator Any() const {
|
||||
Any any(Any::ARRAY, "Vector3");
|
||||
any.append(x, y, z);
|
||||
return any;
|
||||
}
|
||||
|
||||
Vector3::Vector3(const class Color3& v) : x(v.r), y(v.g), z(v.b) {}
|
||||
|
||||
Vector3::Vector3(const class Vector3int32& v) : x((float)v.x), y((float)v.y), z((float)v.z) {}
|
||||
|
||||
Vector3::Vector3(const Vector4int8& v) : x(v.x / 127.0f), y(v.y / 127.0f), z(v.z / 127.0f) {}
|
||||
|
||||
Vector3::Vector3(const class Vector2& v, float _z) : x(v.x), y(v.y), z(_z) {
|
||||
}
|
||||
|
||||
Vector3& Vector3::ignore() {
|
||||
static Vector3 v;
|
||||
return v;
|
||||
}
|
||||
|
||||
const Vector3& Vector3::zero() { static const Vector3 v(0, 0, 0); return v; }
|
||||
const Vector3& Vector3::one() { static const Vector3 v(1, 1, 1); return v; }
|
||||
const Vector3& Vector3::unitX() { static const Vector3 v(1, 0, 0); return v; }
|
||||
const Vector3& Vector3::unitY() { static const Vector3 v(0, 1, 0); return v; }
|
||||
const Vector3& Vector3::unitZ() { static const Vector3 v(0, 0, 1); return v; }
|
||||
const Vector3& Vector3::inf() { static const Vector3 v((float)G3D::finf(), (float)G3D::finf(), (float)G3D::finf()); return v; }
|
||||
const Vector3& Vector3::nan() { static const Vector3 v((float)G3D::fnan(), (float)G3D::fnan(), (float)G3D::fnan()); return v; }
|
||||
const Vector3& Vector3::minFinite(){ static const Vector3 v(-FLT_MAX, -FLT_MAX, -FLT_MAX); return v; }
|
||||
const Vector3& Vector3::maxFinite(){ static const Vector3 v(FLT_MAX, FLT_MAX, FLT_MAX); return v; }
|
||||
|
||||
Vector3::Axis Vector3::primaryAxis() const {
|
||||
|
||||
Axis a = X_AXIS;
|
||||
|
||||
double nx = abs(x);
|
||||
double ny = abs(y);
|
||||
double nz = abs(z);
|
||||
|
||||
if (nx > ny) {
|
||||
if (nx > nz) {
|
||||
a = X_AXIS;
|
||||
} else {
|
||||
a = Z_AXIS;
|
||||
}
|
||||
} else {
|
||||
if (ny > nz) {
|
||||
a = Y_AXIS;
|
||||
} else {
|
||||
a = Z_AXIS;
|
||||
}
|
||||
}
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
|
||||
size_t Vector3::hashCode() const {
|
||||
unsigned int xhash = (*(int*)(void*)(&x));
|
||||
unsigned int yhash = (*(int*)(void*)(&y));
|
||||
unsigned int zhash = (*(int*)(void*)(&z));
|
||||
|
||||
return xhash + (yhash * 37) + (zhash * 101);
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, const Vector3& v) {
|
||||
return os << v.toString();
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
double frand() {
|
||||
return rand() / (double) RAND_MAX;
|
||||
}
|
||||
|
||||
Vector3::Vector3(TextInput& t) {
|
||||
deserialize(t);
|
||||
}
|
||||
|
||||
Vector3::Vector3(BinaryInput& b) {
|
||||
deserialize(b);
|
||||
}
|
||||
|
||||
|
||||
Vector3::Vector3(const class Vector3int16& v) {
|
||||
x = v.x;
|
||||
y = v.y;
|
||||
z = v.z;
|
||||
}
|
||||
|
||||
|
||||
void Vector3::deserialize(BinaryInput& b) {
|
||||
x = b.readFloat32();
|
||||
y = b.readFloat32();
|
||||
z = b.readFloat32();
|
||||
}
|
||||
|
||||
|
||||
void Vector3::deserialize(TextInput& t) {
|
||||
t.readSymbol("(");
|
||||
x = (float)t.readNumber();
|
||||
t.readSymbol(",");
|
||||
y = (float)t.readNumber();
|
||||
t.readSymbol(",");
|
||||
z = (float)t.readNumber();
|
||||
t.readSymbol(")");
|
||||
}
|
||||
|
||||
|
||||
void Vector3::serialize(TextOutput& t) const {
|
||||
t.writeSymbol("(");
|
||||
t.writeNumber(x);
|
||||
t.writeSymbol(",");
|
||||
t.writeNumber(y);
|
||||
t.writeSymbol(",");
|
||||
t.writeNumber(z);
|
||||
t.writeSymbol(")");
|
||||
}
|
||||
|
||||
|
||||
void Vector3::serialize(BinaryOutput& b) const {
|
||||
b.writeFloat32(x);
|
||||
b.writeFloat32(y);
|
||||
b.writeFloat32(z);
|
||||
}
|
||||
|
||||
|
||||
Vector3 Vector3::random(Random& r) {
|
||||
Vector3 result;
|
||||
r.sphere(result.x, result.y, result.z);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
float Vector3::unitize(float fTolerance) {
|
||||
float fMagnitude = magnitude();
|
||||
|
||||
if (fMagnitude > fTolerance) {
|
||||
float fInvMagnitude = 1.0f / fMagnitude;
|
||||
x *= fInvMagnitude;
|
||||
y *= fInvMagnitude;
|
||||
z *= fInvMagnitude;
|
||||
} else {
|
||||
fMagnitude = 0.0f;
|
||||
}
|
||||
|
||||
return fMagnitude;
|
||||
}
|
||||
|
||||
|
||||
Vector3 Vector3::reflectAbout(const Vector3& normal) const {
|
||||
Vector3 out;
|
||||
|
||||
Vector3 N = normal.direction();
|
||||
|
||||
// 2 * normal.dot(this) * normal - this
|
||||
return N * 2 * this->dot(N) - *this;
|
||||
}
|
||||
|
||||
|
||||
Vector3 Vector3::cosHemiRandom(const Vector3& normal, Random& r) {
|
||||
debugAssertM(G3D::fuzzyEq(normal.length(), 1.0f),
|
||||
"cosHemiRandom requires its argument to have unit length");
|
||||
|
||||
float x, y, z;
|
||||
r.cosHemi(x, y, z);
|
||||
|
||||
// Make a coordinate system
|
||||
const Vector3& Z = normal;
|
||||
|
||||
Vector3 X, Y;
|
||||
normal.getTangents(X, Y);
|
||||
|
||||
return
|
||||
x * X +
|
||||
y * Y +
|
||||
z * Z;
|
||||
}
|
||||
|
||||
|
||||
Vector3 Vector3::cosPowHemiRandom(const Vector3& normal, const float k, Random& r) {
|
||||
debugAssertM(G3D::fuzzyEq(normal.length(), 1.0f),
|
||||
"cosPowHemiRandom requires its argument to have unit length");
|
||||
|
||||
float x, y, z;
|
||||
r.cosPowHemi(k, x, y, z);
|
||||
|
||||
// Make a coordinate system
|
||||
const Vector3& Z = normal;
|
||||
|
||||
Vector3 X, Y;
|
||||
normal.getTangents(X, Y);
|
||||
|
||||
return
|
||||
x * X +
|
||||
y * Y +
|
||||
z * Z;
|
||||
}
|
||||
|
||||
|
||||
Vector3 Vector3::hemiRandom(const Vector3& normal, Random& r) {
|
||||
const Vector3& V = Vector3::random(r);
|
||||
|
||||
if (V.dot(normal) < 0) {
|
||||
return -V;
|
||||
} else {
|
||||
return V;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
Vector3 Vector3::reflectionDirection(const Vector3& normal) const {
|
||||
return -reflectAbout(normal).direction();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
Vector3 Vector3::refractionDirection(
|
||||
const Vector3& normal,
|
||||
float iInside,
|
||||
float iOutside) const {
|
||||
|
||||
// From pg. 24 of Henrik Wann Jensen. Realistic Image Synthesis
|
||||
// Using Photon Mapping. AK Peters. ISBN: 1568811470. July 2001.
|
||||
|
||||
// Invert the directions from Wann Jensen's formulation
|
||||
// and normalize the vectors.
|
||||
const Vector3 W = -direction();
|
||||
Vector3 N = normal.direction();
|
||||
|
||||
float h1 = iOutside;
|
||||
float h2 = iInside;
|
||||
|
||||
if (normal.dot(*this) > 0.0f) {
|
||||
h1 = iInside;
|
||||
h2 = iOutside;
|
||||
N = -N;
|
||||
}
|
||||
|
||||
const float hRatio = h1 / h2;
|
||||
const float WdotN = W.dot(N);
|
||||
|
||||
float det = 1.0f - (float)square(hRatio) * (1.0f - (float)square(WdotN));
|
||||
|
||||
if (det < 0) {
|
||||
// Total internal reflection
|
||||
return Vector3::zero();
|
||||
} else {
|
||||
return -hRatio * (W - WdotN * N) - N * sqrt(det);
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void Vector3::orthonormalize (Vector3 akVector[3]) {
|
||||
// If the input vectors are v0, v1, and v2, then the Gram-Schmidt
|
||||
// orthonormalization produces vectors u0, u1, and u2 as follows,
|
||||
//
|
||||
// u0 = v0/|v0|
|
||||
// u1 = (v1-(u0*v1)u0)/|v1-(u0*v1)u0|
|
||||
// u2 = (v2-(u0*v2)u0-(u1*v2)u1)/|v2-(u0*v2)u0-(u1*v2)u1|
|
||||
//
|
||||
// where |A| indicates length of vector A and A*B indicates dot
|
||||
// product of vectors A and B.
|
||||
|
||||
// compute u0
|
||||
akVector[0].unitize();
|
||||
|
||||
// compute u1
|
||||
float fDot0 = akVector[0].dot(akVector[1]);
|
||||
akVector[1] -= akVector[0] * fDot0;
|
||||
akVector[1].unitize();
|
||||
|
||||
// compute u2
|
||||
float fDot1 = akVector[1].dot(akVector[2]);
|
||||
fDot0 = akVector[0].dot(akVector[2]);
|
||||
akVector[2] -= akVector[0] * fDot0 + akVector[1] * fDot1;
|
||||
akVector[2].unitize();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void Vector3::generateOrthonormalBasis (Vector3& rkU, Vector3& rkV,
|
||||
Vector3& rkW, bool bUnitLengthW) {
|
||||
if ( !bUnitLengthW )
|
||||
rkW.unitize();
|
||||
|
||||
if ( G3D::abs(rkW.x) >= G3D::abs(rkW.y)
|
||||
&& G3D::abs(rkW.x) >= G3D::abs(rkW.z) ) {
|
||||
rkU.x = -rkW.y;
|
||||
rkU.y = + rkW.x;
|
||||
rkU.z = 0.0;
|
||||
} else {
|
||||
rkU.x = 0.0;
|
||||
rkU.y = + rkW.z;
|
||||
rkU.z = -rkW.y;
|
||||
}
|
||||
|
||||
rkU.unitize();
|
||||
rkV = rkW.cross(rkU);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
std::string Vector3::toString() const {
|
||||
return G3D::format("(%g, %g, %g)", x, y, z);
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
Matrix3 Vector3::cross() const {
|
||||
return Matrix3( 0, -z, y,
|
||||
z, 0, -x,
|
||||
-y, x, 0);
|
||||
}
|
||||
|
||||
|
||||
void serialize(const Vector3::Axis& a, class BinaryOutput& bo) {
|
||||
bo.writeUInt8((uint8)a);
|
||||
}
|
||||
|
||||
void deserialize(Vector3::Axis& a, class BinaryInput& bi) {
|
||||
a = (Vector3::Axis)bi.readUInt8();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// 2-char swizzles
|
||||
|
||||
Vector2 Vector3::xx() const { return Vector2 (x, x); }
|
||||
Vector2 Vector3::yx() const { return Vector2 (y, x); }
|
||||
Vector2 Vector3::zx() const { return Vector2 (z, x); }
|
||||
Vector2 Vector3::xy() const { return Vector2 (x, y); }
|
||||
Vector2 Vector3::yy() const { return Vector2 (y, y); }
|
||||
Vector2 Vector3::zy() const { return Vector2 (z, y); }
|
||||
Vector2 Vector3::xz() const { return Vector2 (x, z); }
|
||||
Vector2 Vector3::yz() const { return Vector2 (y, z); }
|
||||
Vector2 Vector3::zz() const { return Vector2 (z, z); }
|
||||
|
||||
// 3-char swizzles
|
||||
|
||||
Vector3 Vector3::xxx() const { return Vector3 (x, x, x); }
|
||||
Vector3 Vector3::yxx() const { return Vector3 (y, x, x); }
|
||||
Vector3 Vector3::zxx() const { return Vector3 (z, x, x); }
|
||||
Vector3 Vector3::xyx() const { return Vector3 (x, y, x); }
|
||||
Vector3 Vector3::yyx() const { return Vector3 (y, y, x); }
|
||||
Vector3 Vector3::zyx() const { return Vector3 (z, y, x); }
|
||||
Vector3 Vector3::xzx() const { return Vector3 (x, z, x); }
|
||||
Vector3 Vector3::yzx() const { return Vector3 (y, z, x); }
|
||||
Vector3 Vector3::zzx() const { return Vector3 (z, z, x); }
|
||||
Vector3 Vector3::xxy() const { return Vector3 (x, x, y); }
|
||||
Vector3 Vector3::yxy() const { return Vector3 (y, x, y); }
|
||||
Vector3 Vector3::zxy() const { return Vector3 (z, x, y); }
|
||||
Vector3 Vector3::xyy() const { return Vector3 (x, y, y); }
|
||||
Vector3 Vector3::yyy() const { return Vector3 (y, y, y); }
|
||||
Vector3 Vector3::zyy() const { return Vector3 (z, y, y); }
|
||||
Vector3 Vector3::xzy() const { return Vector3 (x, z, y); }
|
||||
Vector3 Vector3::yzy() const { return Vector3 (y, z, y); }
|
||||
Vector3 Vector3::zzy() const { return Vector3 (z, z, y); }
|
||||
Vector3 Vector3::xxz() const { return Vector3 (x, x, z); }
|
||||
Vector3 Vector3::yxz() const { return Vector3 (y, x, z); }
|
||||
Vector3 Vector3::zxz() const { return Vector3 (z, x, z); }
|
||||
Vector3 Vector3::xyz() const { return Vector3 (x, y, z); }
|
||||
Vector3 Vector3::yyz() const { return Vector3 (y, y, z); }
|
||||
Vector3 Vector3::zyz() const { return Vector3 (z, y, z); }
|
||||
Vector3 Vector3::xzz() const { return Vector3 (x, z, z); }
|
||||
Vector3 Vector3::yzz() const { return Vector3 (y, z, z); }
|
||||
Vector3 Vector3::zzz() const { return Vector3 (z, z, z); }
|
||||
|
||||
// 4-char swizzles
|
||||
|
||||
Vector4 Vector3::xxxx() const { return Vector4 (x, x, x, x); }
|
||||
Vector4 Vector3::yxxx() const { return Vector4 (y, x, x, x); }
|
||||
Vector4 Vector3::zxxx() const { return Vector4 (z, x, x, x); }
|
||||
Vector4 Vector3::xyxx() const { return Vector4 (x, y, x, x); }
|
||||
Vector4 Vector3::yyxx() const { return Vector4 (y, y, x, x); }
|
||||
Vector4 Vector3::zyxx() const { return Vector4 (z, y, x, x); }
|
||||
Vector4 Vector3::xzxx() const { return Vector4 (x, z, x, x); }
|
||||
Vector4 Vector3::yzxx() const { return Vector4 (y, z, x, x); }
|
||||
Vector4 Vector3::zzxx() const { return Vector4 (z, z, x, x); }
|
||||
Vector4 Vector3::xxyx() const { return Vector4 (x, x, y, x); }
|
||||
Vector4 Vector3::yxyx() const { return Vector4 (y, x, y, x); }
|
||||
Vector4 Vector3::zxyx() const { return Vector4 (z, x, y, x); }
|
||||
Vector4 Vector3::xyyx() const { return Vector4 (x, y, y, x); }
|
||||
Vector4 Vector3::yyyx() const { return Vector4 (y, y, y, x); }
|
||||
Vector4 Vector3::zyyx() const { return Vector4 (z, y, y, x); }
|
||||
Vector4 Vector3::xzyx() const { return Vector4 (x, z, y, x); }
|
||||
Vector4 Vector3::yzyx() const { return Vector4 (y, z, y, x); }
|
||||
Vector4 Vector3::zzyx() const { return Vector4 (z, z, y, x); }
|
||||
Vector4 Vector3::xxzx() const { return Vector4 (x, x, z, x); }
|
||||
Vector4 Vector3::yxzx() const { return Vector4 (y, x, z, x); }
|
||||
Vector4 Vector3::zxzx() const { return Vector4 (z, x, z, x); }
|
||||
Vector4 Vector3::xyzx() const { return Vector4 (x, y, z, x); }
|
||||
Vector4 Vector3::yyzx() const { return Vector4 (y, y, z, x); }
|
||||
Vector4 Vector3::zyzx() const { return Vector4 (z, y, z, x); }
|
||||
Vector4 Vector3::xzzx() const { return Vector4 (x, z, z, x); }
|
||||
Vector4 Vector3::yzzx() const { return Vector4 (y, z, z, x); }
|
||||
Vector4 Vector3::zzzx() const { return Vector4 (z, z, z, x); }
|
||||
Vector4 Vector3::xxxy() const { return Vector4 (x, x, x, y); }
|
||||
Vector4 Vector3::yxxy() const { return Vector4 (y, x, x, y); }
|
||||
Vector4 Vector3::zxxy() const { return Vector4 (z, x, x, y); }
|
||||
Vector4 Vector3::xyxy() const { return Vector4 (x, y, x, y); }
|
||||
Vector4 Vector3::yyxy() const { return Vector4 (y, y, x, y); }
|
||||
Vector4 Vector3::zyxy() const { return Vector4 (z, y, x, y); }
|
||||
Vector4 Vector3::xzxy() const { return Vector4 (x, z, x, y); }
|
||||
Vector4 Vector3::yzxy() const { return Vector4 (y, z, x, y); }
|
||||
Vector4 Vector3::zzxy() const { return Vector4 (z, z, x, y); }
|
||||
Vector4 Vector3::xxyy() const { return Vector4 (x, x, y, y); }
|
||||
Vector4 Vector3::yxyy() const { return Vector4 (y, x, y, y); }
|
||||
Vector4 Vector3::zxyy() const { return Vector4 (z, x, y, y); }
|
||||
Vector4 Vector3::xyyy() const { return Vector4 (x, y, y, y); }
|
||||
Vector4 Vector3::yyyy() const { return Vector4 (y, y, y, y); }
|
||||
Vector4 Vector3::zyyy() const { return Vector4 (z, y, y, y); }
|
||||
Vector4 Vector3::xzyy() const { return Vector4 (x, z, y, y); }
|
||||
Vector4 Vector3::yzyy() const { return Vector4 (y, z, y, y); }
|
||||
Vector4 Vector3::zzyy() const { return Vector4 (z, z, y, y); }
|
||||
Vector4 Vector3::xxzy() const { return Vector4 (x, x, z, y); }
|
||||
Vector4 Vector3::yxzy() const { return Vector4 (y, x, z, y); }
|
||||
Vector4 Vector3::zxzy() const { return Vector4 (z, x, z, y); }
|
||||
Vector4 Vector3::xyzy() const { return Vector4 (x, y, z, y); }
|
||||
Vector4 Vector3::yyzy() const { return Vector4 (y, y, z, y); }
|
||||
Vector4 Vector3::zyzy() const { return Vector4 (z, y, z, y); }
|
||||
Vector4 Vector3::xzzy() const { return Vector4 (x, z, z, y); }
|
||||
Vector4 Vector3::yzzy() const { return Vector4 (y, z, z, y); }
|
||||
Vector4 Vector3::zzzy() const { return Vector4 (z, z, z, y); }
|
||||
Vector4 Vector3::xxxz() const { return Vector4 (x, x, x, z); }
|
||||
Vector4 Vector3::yxxz() const { return Vector4 (y, x, x, z); }
|
||||
Vector4 Vector3::zxxz() const { return Vector4 (z, x, x, z); }
|
||||
Vector4 Vector3::xyxz() const { return Vector4 (x, y, x, z); }
|
||||
Vector4 Vector3::yyxz() const { return Vector4 (y, y, x, z); }
|
||||
Vector4 Vector3::zyxz() const { return Vector4 (z, y, x, z); }
|
||||
Vector4 Vector3::xzxz() const { return Vector4 (x, z, x, z); }
|
||||
Vector4 Vector3::yzxz() const { return Vector4 (y, z, x, z); }
|
||||
Vector4 Vector3::zzxz() const { return Vector4 (z, z, x, z); }
|
||||
Vector4 Vector3::xxyz() const { return Vector4 (x, x, y, z); }
|
||||
Vector4 Vector3::yxyz() const { return Vector4 (y, x, y, z); }
|
||||
Vector4 Vector3::zxyz() const { return Vector4 (z, x, y, z); }
|
||||
Vector4 Vector3::xyyz() const { return Vector4 (x, y, y, z); }
|
||||
Vector4 Vector3::yyyz() const { return Vector4 (y, y, y, z); }
|
||||
Vector4 Vector3::zyyz() const { return Vector4 (z, y, y, z); }
|
||||
Vector4 Vector3::xzyz() const { return Vector4 (x, z, y, z); }
|
||||
Vector4 Vector3::yzyz() const { return Vector4 (y, z, y, z); }
|
||||
Vector4 Vector3::zzyz() const { return Vector4 (z, z, y, z); }
|
||||
Vector4 Vector3::xxzz() const { return Vector4 (x, x, z, z); }
|
||||
Vector4 Vector3::yxzz() const { return Vector4 (y, x, z, z); }
|
||||
Vector4 Vector3::zxzz() const { return Vector4 (z, x, z, z); }
|
||||
Vector4 Vector3::xyzz() const { return Vector4 (x, y, z, z); }
|
||||
Vector4 Vector3::yyzz() const { return Vector4 (y, y, z, z); }
|
||||
Vector4 Vector3::zyzz() const { return Vector4 (z, y, z, z); }
|
||||
Vector4 Vector3::xzzz() const { return Vector4 (x, z, z, z); }
|
||||
Vector4 Vector3::yzzz() const { return Vector4 (y, z, z, z); }
|
||||
Vector4 Vector3::zzzz() const { return Vector4 (z, z, z, z); }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
} // namespace
|
||||
520
externals/g3dlite/Vector4.cpp
vendored
Normal file
520
externals/g3dlite/Vector4.cpp
vendored
Normal file
@@ -0,0 +1,520 @@
|
||||
/**
|
||||
@file Vector4.cpp
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
@created 2001-07-09
|
||||
@edited 2009-11-29
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <limits>
|
||||
#include "G3D/Vector4.h"
|
||||
#include "G3D/Color4.h"
|
||||
#include "G3D/g3dmath.h"
|
||||
#include "G3D/stringutils.h"
|
||||
#include "G3D/BinaryInput.h"
|
||||
#include "G3D/BinaryOutput.h"
|
||||
#include "G3D/Vector4int8.h"
|
||||
#include "G3D/Matrix4.h"
|
||||
#include "G3D/Any.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
Vector4::Vector4(const Any& any) {
|
||||
any.verifyName("Vector4");
|
||||
any.verifyType(Any::TABLE, Any::ARRAY);
|
||||
any.verifySize(4);
|
||||
|
||||
if (any.type() == Any::ARRAY) {
|
||||
x = any[0];
|
||||
y = any[1];
|
||||
z = any[2];
|
||||
w = any[3];
|
||||
} else {
|
||||
// Table
|
||||
x = any["x"];
|
||||
y = any["y"];
|
||||
z = any["z"];
|
||||
w = any["w"];
|
||||
}
|
||||
}
|
||||
|
||||
Vector4::operator Any() const {
|
||||
Any any(Any::ARRAY, "Vector4");
|
||||
any.append(x, y, z, w);
|
||||
return any;
|
||||
}
|
||||
|
||||
|
||||
Vector4::Vector4(const Vector4int8& v) : x(v.x / 127.0f), y(v.y / 127.0f), z(v.z / 127.0f), w(v.w / 127.0f) {
|
||||
}
|
||||
|
||||
|
||||
const Vector4& Vector4::inf() {
|
||||
static const Vector4 v((float)G3D::finf(), (float)G3D::finf(), (float)G3D::finf(), (float)G3D::finf());
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
const Vector4& Vector4::zero() {
|
||||
static const Vector4 v(0,0,0,0);
|
||||
return v;
|
||||
}
|
||||
|
||||
const Vector4& Vector4::nan() {
|
||||
static Vector4 v((float)G3D::fnan(), (float)G3D::fnan(), (float)G3D::fnan(), (float)G3D::fnan());
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
size_t Vector4::hashCode() const {
|
||||
unsigned int xhash = (*(int*)(void*)(&x));
|
||||
unsigned int yhash = (*(int*)(void*)(&y));
|
||||
unsigned int zhash = (*(int*)(void*)(&z));
|
||||
unsigned int whash = (*(int*)(void*)(&w));
|
||||
|
||||
return xhash + (yhash * 37) + (zhash * 101) + (whash * 241);
|
||||
}
|
||||
|
||||
|
||||
Vector4::Vector4(const class Color4& c) {
|
||||
x = c.r;
|
||||
y = c.g;
|
||||
z = c.b;
|
||||
w = c.a;
|
||||
}
|
||||
|
||||
|
||||
Vector4::Vector4(const Vector2& v1, const Vector2& v2) {
|
||||
x = v1.x;
|
||||
y = v1.y;
|
||||
z = v2.x;
|
||||
w = v2.y;
|
||||
}
|
||||
|
||||
|
||||
Vector4::Vector4(const Vector2& v1, float fz, float fw) {
|
||||
x = v1.x;
|
||||
y = v1.y;
|
||||
z = fz;
|
||||
w = fw;
|
||||
}
|
||||
|
||||
Vector4::Vector4(BinaryInput& b) {
|
||||
deserialize(b);
|
||||
}
|
||||
|
||||
|
||||
void Vector4::deserialize(BinaryInput& b) {
|
||||
x = b.readFloat32();
|
||||
y = b.readFloat32();
|
||||
z = b.readFloat32();
|
||||
w = b.readFloat32();
|
||||
}
|
||||
|
||||
|
||||
void Vector4::serialize(BinaryOutput& b) const {
|
||||
b.writeFloat32(x);
|
||||
b.writeFloat32(y);
|
||||
b.writeFloat32(z);
|
||||
b.writeFloat32(w);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
Vector4 Vector4::operator*(const Matrix4& M) const {
|
||||
Vector4 result;
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
result[i] = 0.0f;
|
||||
for (int j = 0; j < 4; ++j) {
|
||||
result[i] += (*this)[j] * M[j][i];
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
Vector4 Vector4::operator/ (float fScalar) const {
|
||||
Vector4 kQuot;
|
||||
|
||||
if ( fScalar != 0.0 ) {
|
||||
float fInvScalar = 1.0f / fScalar;
|
||||
kQuot.x = fInvScalar * x;
|
||||
kQuot.y = fInvScalar * y;
|
||||
kQuot.z = fInvScalar * z;
|
||||
kQuot.w = fInvScalar * w;
|
||||
return kQuot;
|
||||
} else {
|
||||
return Vector4::inf();
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
Vector4& Vector4::operator/= (float fScalar) {
|
||||
if (fScalar != 0.0f) {
|
||||
float fInvScalar = 1.0f / fScalar;
|
||||
x *= fInvScalar;
|
||||
y *= fInvScalar;
|
||||
z *= fInvScalar;
|
||||
w *= fInvScalar;
|
||||
} else {
|
||||
*this = Vector4::inf();
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
std::string Vector4::toString() const {
|
||||
return G3D::format("(%g, %g, %g, %g)", x, y, z, w);
|
||||
}
|
||||
// 2-char swizzles
|
||||
|
||||
Vector2 Vector4::xx() const { return Vector2 (x, x); }
|
||||
Vector2 Vector4::yx() const { return Vector2 (y, x); }
|
||||
Vector2 Vector4::zx() const { return Vector2 (z, x); }
|
||||
Vector2 Vector4::wx() const { return Vector2 (w, x); }
|
||||
Vector2 Vector4::xy() const { return Vector2 (x, y); }
|
||||
Vector2 Vector4::yy() const { return Vector2 (y, y); }
|
||||
Vector2 Vector4::zy() const { return Vector2 (z, y); }
|
||||
Vector2 Vector4::wy() const { return Vector2 (w, y); }
|
||||
Vector2 Vector4::xz() const { return Vector2 (x, z); }
|
||||
Vector2 Vector4::yz() const { return Vector2 (y, z); }
|
||||
Vector2 Vector4::zz() const { return Vector2 (z, z); }
|
||||
Vector2 Vector4::wz() const { return Vector2 (w, z); }
|
||||
Vector2 Vector4::xw() const { return Vector2 (x, w); }
|
||||
Vector2 Vector4::yw() const { return Vector2 (y, w); }
|
||||
Vector2 Vector4::zw() const { return Vector2 (z, w); }
|
||||
Vector2 Vector4::ww() const { return Vector2 (w, w); }
|
||||
|
||||
// 3-char swizzles
|
||||
|
||||
Vector3 Vector4::xxx() const { return Vector3 (x, x, x); }
|
||||
Vector3 Vector4::yxx() const { return Vector3 (y, x, x); }
|
||||
Vector3 Vector4::zxx() const { return Vector3 (z, x, x); }
|
||||
Vector3 Vector4::wxx() const { return Vector3 (w, x, x); }
|
||||
Vector3 Vector4::xyx() const { return Vector3 (x, y, x); }
|
||||
Vector3 Vector4::yyx() const { return Vector3 (y, y, x); }
|
||||
Vector3 Vector4::zyx() const { return Vector3 (z, y, x); }
|
||||
Vector3 Vector4::wyx() const { return Vector3 (w, y, x); }
|
||||
Vector3 Vector4::xzx() const { return Vector3 (x, z, x); }
|
||||
Vector3 Vector4::yzx() const { return Vector3 (y, z, x); }
|
||||
Vector3 Vector4::zzx() const { return Vector3 (z, z, x); }
|
||||
Vector3 Vector4::wzx() const { return Vector3 (w, z, x); }
|
||||
Vector3 Vector4::xwx() const { return Vector3 (x, w, x); }
|
||||
Vector3 Vector4::ywx() const { return Vector3 (y, w, x); }
|
||||
Vector3 Vector4::zwx() const { return Vector3 (z, w, x); }
|
||||
Vector3 Vector4::wwx() const { return Vector3 (w, w, x); }
|
||||
Vector3 Vector4::xxy() const { return Vector3 (x, x, y); }
|
||||
Vector3 Vector4::yxy() const { return Vector3 (y, x, y); }
|
||||
Vector3 Vector4::zxy() const { return Vector3 (z, x, y); }
|
||||
Vector3 Vector4::wxy() const { return Vector3 (w, x, y); }
|
||||
Vector3 Vector4::xyy() const { return Vector3 (x, y, y); }
|
||||
Vector3 Vector4::yyy() const { return Vector3 (y, y, y); }
|
||||
Vector3 Vector4::zyy() const { return Vector3 (z, y, y); }
|
||||
Vector3 Vector4::wyy() const { return Vector3 (w, y, y); }
|
||||
Vector3 Vector4::xzy() const { return Vector3 (x, z, y); }
|
||||
Vector3 Vector4::yzy() const { return Vector3 (y, z, y); }
|
||||
Vector3 Vector4::zzy() const { return Vector3 (z, z, y); }
|
||||
Vector3 Vector4::wzy() const { return Vector3 (w, z, y); }
|
||||
Vector3 Vector4::xwy() const { return Vector3 (x, w, y); }
|
||||
Vector3 Vector4::ywy() const { return Vector3 (y, w, y); }
|
||||
Vector3 Vector4::zwy() const { return Vector3 (z, w, y); }
|
||||
Vector3 Vector4::wwy() const { return Vector3 (w, w, y); }
|
||||
Vector3 Vector4::xxz() const { return Vector3 (x, x, z); }
|
||||
Vector3 Vector4::yxz() const { return Vector3 (y, x, z); }
|
||||
Vector3 Vector4::zxz() const { return Vector3 (z, x, z); }
|
||||
Vector3 Vector4::wxz() const { return Vector3 (w, x, z); }
|
||||
Vector3 Vector4::xyz() const { return Vector3 (x, y, z); }
|
||||
Vector3 Vector4::yyz() const { return Vector3 (y, y, z); }
|
||||
Vector3 Vector4::zyz() const { return Vector3 (z, y, z); }
|
||||
Vector3 Vector4::wyz() const { return Vector3 (w, y, z); }
|
||||
Vector3 Vector4::xzz() const { return Vector3 (x, z, z); }
|
||||
Vector3 Vector4::yzz() const { return Vector3 (y, z, z); }
|
||||
Vector3 Vector4::zzz() const { return Vector3 (z, z, z); }
|
||||
Vector3 Vector4::wzz() const { return Vector3 (w, z, z); }
|
||||
Vector3 Vector4::xwz() const { return Vector3 (x, w, z); }
|
||||
Vector3 Vector4::ywz() const { return Vector3 (y, w, z); }
|
||||
Vector3 Vector4::zwz() const { return Vector3 (z, w, z); }
|
||||
Vector3 Vector4::wwz() const { return Vector3 (w, w, z); }
|
||||
Vector3 Vector4::xxw() const { return Vector3 (x, x, w); }
|
||||
Vector3 Vector4::yxw() const { return Vector3 (y, x, w); }
|
||||
Vector3 Vector4::zxw() const { return Vector3 (z, x, w); }
|
||||
Vector3 Vector4::wxw() const { return Vector3 (w, x, w); }
|
||||
Vector3 Vector4::xyw() const { return Vector3 (x, y, w); }
|
||||
Vector3 Vector4::yyw() const { return Vector3 (y, y, w); }
|
||||
Vector3 Vector4::zyw() const { return Vector3 (z, y, w); }
|
||||
Vector3 Vector4::wyw() const { return Vector3 (w, y, w); }
|
||||
Vector3 Vector4::xzw() const { return Vector3 (x, z, w); }
|
||||
Vector3 Vector4::yzw() const { return Vector3 (y, z, w); }
|
||||
Vector3 Vector4::zzw() const { return Vector3 (z, z, w); }
|
||||
Vector3 Vector4::wzw() const { return Vector3 (w, z, w); }
|
||||
Vector3 Vector4::xww() const { return Vector3 (x, w, w); }
|
||||
Vector3 Vector4::yww() const { return Vector3 (y, w, w); }
|
||||
Vector3 Vector4::zww() const { return Vector3 (z, w, w); }
|
||||
Vector3 Vector4::www() const { return Vector3 (w, w, w); }
|
||||
|
||||
// 4-char swizzles
|
||||
|
||||
Vector4 Vector4::xxxx() const { return Vector4 (x, x, x, x); }
|
||||
Vector4 Vector4::yxxx() const { return Vector4 (y, x, x, x); }
|
||||
Vector4 Vector4::zxxx() const { return Vector4 (z, x, x, x); }
|
||||
Vector4 Vector4::wxxx() const { return Vector4 (w, x, x, x); }
|
||||
Vector4 Vector4::xyxx() const { return Vector4 (x, y, x, x); }
|
||||
Vector4 Vector4::yyxx() const { return Vector4 (y, y, x, x); }
|
||||
Vector4 Vector4::zyxx() const { return Vector4 (z, y, x, x); }
|
||||
Vector4 Vector4::wyxx() const { return Vector4 (w, y, x, x); }
|
||||
Vector4 Vector4::xzxx() const { return Vector4 (x, z, x, x); }
|
||||
Vector4 Vector4::yzxx() const { return Vector4 (y, z, x, x); }
|
||||
Vector4 Vector4::zzxx() const { return Vector4 (z, z, x, x); }
|
||||
Vector4 Vector4::wzxx() const { return Vector4 (w, z, x, x); }
|
||||
Vector4 Vector4::xwxx() const { return Vector4 (x, w, x, x); }
|
||||
Vector4 Vector4::ywxx() const { return Vector4 (y, w, x, x); }
|
||||
Vector4 Vector4::zwxx() const { return Vector4 (z, w, x, x); }
|
||||
Vector4 Vector4::wwxx() const { return Vector4 (w, w, x, x); }
|
||||
Vector4 Vector4::xxyx() const { return Vector4 (x, x, y, x); }
|
||||
Vector4 Vector4::yxyx() const { return Vector4 (y, x, y, x); }
|
||||
Vector4 Vector4::zxyx() const { return Vector4 (z, x, y, x); }
|
||||
Vector4 Vector4::wxyx() const { return Vector4 (w, x, y, x); }
|
||||
Vector4 Vector4::xyyx() const { return Vector4 (x, y, y, x); }
|
||||
Vector4 Vector4::yyyx() const { return Vector4 (y, y, y, x); }
|
||||
Vector4 Vector4::zyyx() const { return Vector4 (z, y, y, x); }
|
||||
Vector4 Vector4::wyyx() const { return Vector4 (w, y, y, x); }
|
||||
Vector4 Vector4::xzyx() const { return Vector4 (x, z, y, x); }
|
||||
Vector4 Vector4::yzyx() const { return Vector4 (y, z, y, x); }
|
||||
Vector4 Vector4::zzyx() const { return Vector4 (z, z, y, x); }
|
||||
Vector4 Vector4::wzyx() const { return Vector4 (w, z, y, x); }
|
||||
Vector4 Vector4::xwyx() const { return Vector4 (x, w, y, x); }
|
||||
Vector4 Vector4::ywyx() const { return Vector4 (y, w, y, x); }
|
||||
Vector4 Vector4::zwyx() const { return Vector4 (z, w, y, x); }
|
||||
Vector4 Vector4::wwyx() const { return Vector4 (w, w, y, x); }
|
||||
Vector4 Vector4::xxzx() const { return Vector4 (x, x, z, x); }
|
||||
Vector4 Vector4::yxzx() const { return Vector4 (y, x, z, x); }
|
||||
Vector4 Vector4::zxzx() const { return Vector4 (z, x, z, x); }
|
||||
Vector4 Vector4::wxzx() const { return Vector4 (w, x, z, x); }
|
||||
Vector4 Vector4::xyzx() const { return Vector4 (x, y, z, x); }
|
||||
Vector4 Vector4::yyzx() const { return Vector4 (y, y, z, x); }
|
||||
Vector4 Vector4::zyzx() const { return Vector4 (z, y, z, x); }
|
||||
Vector4 Vector4::wyzx() const { return Vector4 (w, y, z, x); }
|
||||
Vector4 Vector4::xzzx() const { return Vector4 (x, z, z, x); }
|
||||
Vector4 Vector4::yzzx() const { return Vector4 (y, z, z, x); }
|
||||
Vector4 Vector4::zzzx() const { return Vector4 (z, z, z, x); }
|
||||
Vector4 Vector4::wzzx() const { return Vector4 (w, z, z, x); }
|
||||
Vector4 Vector4::xwzx() const { return Vector4 (x, w, z, x); }
|
||||
Vector4 Vector4::ywzx() const { return Vector4 (y, w, z, x); }
|
||||
Vector4 Vector4::zwzx() const { return Vector4 (z, w, z, x); }
|
||||
Vector4 Vector4::wwzx() const { return Vector4 (w, w, z, x); }
|
||||
Vector4 Vector4::xxwx() const { return Vector4 (x, x, w, x); }
|
||||
Vector4 Vector4::yxwx() const { return Vector4 (y, x, w, x); }
|
||||
Vector4 Vector4::zxwx() const { return Vector4 (z, x, w, x); }
|
||||
Vector4 Vector4::wxwx() const { return Vector4 (w, x, w, x); }
|
||||
Vector4 Vector4::xywx() const { return Vector4 (x, y, w, x); }
|
||||
Vector4 Vector4::yywx() const { return Vector4 (y, y, w, x); }
|
||||
Vector4 Vector4::zywx() const { return Vector4 (z, y, w, x); }
|
||||
Vector4 Vector4::wywx() const { return Vector4 (w, y, w, x); }
|
||||
Vector4 Vector4::xzwx() const { return Vector4 (x, z, w, x); }
|
||||
Vector4 Vector4::yzwx() const { return Vector4 (y, z, w, x); }
|
||||
Vector4 Vector4::zzwx() const { return Vector4 (z, z, w, x); }
|
||||
Vector4 Vector4::wzwx() const { return Vector4 (w, z, w, x); }
|
||||
Vector4 Vector4::xwwx() const { return Vector4 (x, w, w, x); }
|
||||
Vector4 Vector4::ywwx() const { return Vector4 (y, w, w, x); }
|
||||
Vector4 Vector4::zwwx() const { return Vector4 (z, w, w, x); }
|
||||
Vector4 Vector4::wwwx() const { return Vector4 (w, w, w, x); }
|
||||
Vector4 Vector4::xxxy() const { return Vector4 (x, x, x, y); }
|
||||
Vector4 Vector4::yxxy() const { return Vector4 (y, x, x, y); }
|
||||
Vector4 Vector4::zxxy() const { return Vector4 (z, x, x, y); }
|
||||
Vector4 Vector4::wxxy() const { return Vector4 (w, x, x, y); }
|
||||
Vector4 Vector4::xyxy() const { return Vector4 (x, y, x, y); }
|
||||
Vector4 Vector4::yyxy() const { return Vector4 (y, y, x, y); }
|
||||
Vector4 Vector4::zyxy() const { return Vector4 (z, y, x, y); }
|
||||
Vector4 Vector4::wyxy() const { return Vector4 (w, y, x, y); }
|
||||
Vector4 Vector4::xzxy() const { return Vector4 (x, z, x, y); }
|
||||
Vector4 Vector4::yzxy() const { return Vector4 (y, z, x, y); }
|
||||
Vector4 Vector4::zzxy() const { return Vector4 (z, z, x, y); }
|
||||
Vector4 Vector4::wzxy() const { return Vector4 (w, z, x, y); }
|
||||
Vector4 Vector4::xwxy() const { return Vector4 (x, w, x, y); }
|
||||
Vector4 Vector4::ywxy() const { return Vector4 (y, w, x, y); }
|
||||
Vector4 Vector4::zwxy() const { return Vector4 (z, w, x, y); }
|
||||
Vector4 Vector4::wwxy() const { return Vector4 (w, w, x, y); }
|
||||
Vector4 Vector4::xxyy() const { return Vector4 (x, x, y, y); }
|
||||
Vector4 Vector4::yxyy() const { return Vector4 (y, x, y, y); }
|
||||
Vector4 Vector4::zxyy() const { return Vector4 (z, x, y, y); }
|
||||
Vector4 Vector4::wxyy() const { return Vector4 (w, x, y, y); }
|
||||
Vector4 Vector4::xyyy() const { return Vector4 (x, y, y, y); }
|
||||
Vector4 Vector4::yyyy() const { return Vector4 (y, y, y, y); }
|
||||
Vector4 Vector4::zyyy() const { return Vector4 (z, y, y, y); }
|
||||
Vector4 Vector4::wyyy() const { return Vector4 (w, y, y, y); }
|
||||
Vector4 Vector4::xzyy() const { return Vector4 (x, z, y, y); }
|
||||
Vector4 Vector4::yzyy() const { return Vector4 (y, z, y, y); }
|
||||
Vector4 Vector4::zzyy() const { return Vector4 (z, z, y, y); }
|
||||
Vector4 Vector4::wzyy() const { return Vector4 (w, z, y, y); }
|
||||
Vector4 Vector4::xwyy() const { return Vector4 (x, w, y, y); }
|
||||
Vector4 Vector4::ywyy() const { return Vector4 (y, w, y, y); }
|
||||
Vector4 Vector4::zwyy() const { return Vector4 (z, w, y, y); }
|
||||
Vector4 Vector4::wwyy() const { return Vector4 (w, w, y, y); }
|
||||
Vector4 Vector4::xxzy() const { return Vector4 (x, x, z, y); }
|
||||
Vector4 Vector4::yxzy() const { return Vector4 (y, x, z, y); }
|
||||
Vector4 Vector4::zxzy() const { return Vector4 (z, x, z, y); }
|
||||
Vector4 Vector4::wxzy() const { return Vector4 (w, x, z, y); }
|
||||
Vector4 Vector4::xyzy() const { return Vector4 (x, y, z, y); }
|
||||
Vector4 Vector4::yyzy() const { return Vector4 (y, y, z, y); }
|
||||
Vector4 Vector4::zyzy() const { return Vector4 (z, y, z, y); }
|
||||
Vector4 Vector4::wyzy() const { return Vector4 (w, y, z, y); }
|
||||
Vector4 Vector4::xzzy() const { return Vector4 (x, z, z, y); }
|
||||
Vector4 Vector4::yzzy() const { return Vector4 (y, z, z, y); }
|
||||
Vector4 Vector4::zzzy() const { return Vector4 (z, z, z, y); }
|
||||
Vector4 Vector4::wzzy() const { return Vector4 (w, z, z, y); }
|
||||
Vector4 Vector4::xwzy() const { return Vector4 (x, w, z, y); }
|
||||
Vector4 Vector4::ywzy() const { return Vector4 (y, w, z, y); }
|
||||
Vector4 Vector4::zwzy() const { return Vector4 (z, w, z, y); }
|
||||
Vector4 Vector4::wwzy() const { return Vector4 (w, w, z, y); }
|
||||
Vector4 Vector4::xxwy() const { return Vector4 (x, x, w, y); }
|
||||
Vector4 Vector4::yxwy() const { return Vector4 (y, x, w, y); }
|
||||
Vector4 Vector4::zxwy() const { return Vector4 (z, x, w, y); }
|
||||
Vector4 Vector4::wxwy() const { return Vector4 (w, x, w, y); }
|
||||
Vector4 Vector4::xywy() const { return Vector4 (x, y, w, y); }
|
||||
Vector4 Vector4::yywy() const { return Vector4 (y, y, w, y); }
|
||||
Vector4 Vector4::zywy() const { return Vector4 (z, y, w, y); }
|
||||
Vector4 Vector4::wywy() const { return Vector4 (w, y, w, y); }
|
||||
Vector4 Vector4::xzwy() const { return Vector4 (x, z, w, y); }
|
||||
Vector4 Vector4::yzwy() const { return Vector4 (y, z, w, y); }
|
||||
Vector4 Vector4::zzwy() const { return Vector4 (z, z, w, y); }
|
||||
Vector4 Vector4::wzwy() const { return Vector4 (w, z, w, y); }
|
||||
Vector4 Vector4::xwwy() const { return Vector4 (x, w, w, y); }
|
||||
Vector4 Vector4::ywwy() const { return Vector4 (y, w, w, y); }
|
||||
Vector4 Vector4::zwwy() const { return Vector4 (z, w, w, y); }
|
||||
Vector4 Vector4::wwwy() const { return Vector4 (w, w, w, y); }
|
||||
Vector4 Vector4::xxxz() const { return Vector4 (x, x, x, z); }
|
||||
Vector4 Vector4::yxxz() const { return Vector4 (y, x, x, z); }
|
||||
Vector4 Vector4::zxxz() const { return Vector4 (z, x, x, z); }
|
||||
Vector4 Vector4::wxxz() const { return Vector4 (w, x, x, z); }
|
||||
Vector4 Vector4::xyxz() const { return Vector4 (x, y, x, z); }
|
||||
Vector4 Vector4::yyxz() const { return Vector4 (y, y, x, z); }
|
||||
Vector4 Vector4::zyxz() const { return Vector4 (z, y, x, z); }
|
||||
Vector4 Vector4::wyxz() const { return Vector4 (w, y, x, z); }
|
||||
Vector4 Vector4::xzxz() const { return Vector4 (x, z, x, z); }
|
||||
Vector4 Vector4::yzxz() const { return Vector4 (y, z, x, z); }
|
||||
Vector4 Vector4::zzxz() const { return Vector4 (z, z, x, z); }
|
||||
Vector4 Vector4::wzxz() const { return Vector4 (w, z, x, z); }
|
||||
Vector4 Vector4::xwxz() const { return Vector4 (x, w, x, z); }
|
||||
Vector4 Vector4::ywxz() const { return Vector4 (y, w, x, z); }
|
||||
Vector4 Vector4::zwxz() const { return Vector4 (z, w, x, z); }
|
||||
Vector4 Vector4::wwxz() const { return Vector4 (w, w, x, z); }
|
||||
Vector4 Vector4::xxyz() const { return Vector4 (x, x, y, z); }
|
||||
Vector4 Vector4::yxyz() const { return Vector4 (y, x, y, z); }
|
||||
Vector4 Vector4::zxyz() const { return Vector4 (z, x, y, z); }
|
||||
Vector4 Vector4::wxyz() const { return Vector4 (w, x, y, z); }
|
||||
Vector4 Vector4::xyyz() const { return Vector4 (x, y, y, z); }
|
||||
Vector4 Vector4::yyyz() const { return Vector4 (y, y, y, z); }
|
||||
Vector4 Vector4::zyyz() const { return Vector4 (z, y, y, z); }
|
||||
Vector4 Vector4::wyyz() const { return Vector4 (w, y, y, z); }
|
||||
Vector4 Vector4::xzyz() const { return Vector4 (x, z, y, z); }
|
||||
Vector4 Vector4::yzyz() const { return Vector4 (y, z, y, z); }
|
||||
Vector4 Vector4::zzyz() const { return Vector4 (z, z, y, z); }
|
||||
Vector4 Vector4::wzyz() const { return Vector4 (w, z, y, z); }
|
||||
Vector4 Vector4::xwyz() const { return Vector4 (x, w, y, z); }
|
||||
Vector4 Vector4::ywyz() const { return Vector4 (y, w, y, z); }
|
||||
Vector4 Vector4::zwyz() const { return Vector4 (z, w, y, z); }
|
||||
Vector4 Vector4::wwyz() const { return Vector4 (w, w, y, z); }
|
||||
Vector4 Vector4::xxzz() const { return Vector4 (x, x, z, z); }
|
||||
Vector4 Vector4::yxzz() const { return Vector4 (y, x, z, z); }
|
||||
Vector4 Vector4::zxzz() const { return Vector4 (z, x, z, z); }
|
||||
Vector4 Vector4::wxzz() const { return Vector4 (w, x, z, z); }
|
||||
Vector4 Vector4::xyzz() const { return Vector4 (x, y, z, z); }
|
||||
Vector4 Vector4::yyzz() const { return Vector4 (y, y, z, z); }
|
||||
Vector4 Vector4::zyzz() const { return Vector4 (z, y, z, z); }
|
||||
Vector4 Vector4::wyzz() const { return Vector4 (w, y, z, z); }
|
||||
Vector4 Vector4::xzzz() const { return Vector4 (x, z, z, z); }
|
||||
Vector4 Vector4::yzzz() const { return Vector4 (y, z, z, z); }
|
||||
Vector4 Vector4::zzzz() const { return Vector4 (z, z, z, z); }
|
||||
Vector4 Vector4::wzzz() const { return Vector4 (w, z, z, z); }
|
||||
Vector4 Vector4::xwzz() const { return Vector4 (x, w, z, z); }
|
||||
Vector4 Vector4::ywzz() const { return Vector4 (y, w, z, z); }
|
||||
Vector4 Vector4::zwzz() const { return Vector4 (z, w, z, z); }
|
||||
Vector4 Vector4::wwzz() const { return Vector4 (w, w, z, z); }
|
||||
Vector4 Vector4::xxwz() const { return Vector4 (x, x, w, z); }
|
||||
Vector4 Vector4::yxwz() const { return Vector4 (y, x, w, z); }
|
||||
Vector4 Vector4::zxwz() const { return Vector4 (z, x, w, z); }
|
||||
Vector4 Vector4::wxwz() const { return Vector4 (w, x, w, z); }
|
||||
Vector4 Vector4::xywz() const { return Vector4 (x, y, w, z); }
|
||||
Vector4 Vector4::yywz() const { return Vector4 (y, y, w, z); }
|
||||
Vector4 Vector4::zywz() const { return Vector4 (z, y, w, z); }
|
||||
Vector4 Vector4::wywz() const { return Vector4 (w, y, w, z); }
|
||||
Vector4 Vector4::xzwz() const { return Vector4 (x, z, w, z); }
|
||||
Vector4 Vector4::yzwz() const { return Vector4 (y, z, w, z); }
|
||||
Vector4 Vector4::zzwz() const { return Vector4 (z, z, w, z); }
|
||||
Vector4 Vector4::wzwz() const { return Vector4 (w, z, w, z); }
|
||||
Vector4 Vector4::xwwz() const { return Vector4 (x, w, w, z); }
|
||||
Vector4 Vector4::ywwz() const { return Vector4 (y, w, w, z); }
|
||||
Vector4 Vector4::zwwz() const { return Vector4 (z, w, w, z); }
|
||||
Vector4 Vector4::wwwz() const { return Vector4 (w, w, w, z); }
|
||||
Vector4 Vector4::xxxw() const { return Vector4 (x, x, x, w); }
|
||||
Vector4 Vector4::yxxw() const { return Vector4 (y, x, x, w); }
|
||||
Vector4 Vector4::zxxw() const { return Vector4 (z, x, x, w); }
|
||||
Vector4 Vector4::wxxw() const { return Vector4 (w, x, x, w); }
|
||||
Vector4 Vector4::xyxw() const { return Vector4 (x, y, x, w); }
|
||||
Vector4 Vector4::yyxw() const { return Vector4 (y, y, x, w); }
|
||||
Vector4 Vector4::zyxw() const { return Vector4 (z, y, x, w); }
|
||||
Vector4 Vector4::wyxw() const { return Vector4 (w, y, x, w); }
|
||||
Vector4 Vector4::xzxw() const { return Vector4 (x, z, x, w); }
|
||||
Vector4 Vector4::yzxw() const { return Vector4 (y, z, x, w); }
|
||||
Vector4 Vector4::zzxw() const { return Vector4 (z, z, x, w); }
|
||||
Vector4 Vector4::wzxw() const { return Vector4 (w, z, x, w); }
|
||||
Vector4 Vector4::xwxw() const { return Vector4 (x, w, x, w); }
|
||||
Vector4 Vector4::ywxw() const { return Vector4 (y, w, x, w); }
|
||||
Vector4 Vector4::zwxw() const { return Vector4 (z, w, x, w); }
|
||||
Vector4 Vector4::wwxw() const { return Vector4 (w, w, x, w); }
|
||||
Vector4 Vector4::xxyw() const { return Vector4 (x, x, y, w); }
|
||||
Vector4 Vector4::yxyw() const { return Vector4 (y, x, y, w); }
|
||||
Vector4 Vector4::zxyw() const { return Vector4 (z, x, y, w); }
|
||||
Vector4 Vector4::wxyw() const { return Vector4 (w, x, y, w); }
|
||||
Vector4 Vector4::xyyw() const { return Vector4 (x, y, y, w); }
|
||||
Vector4 Vector4::yyyw() const { return Vector4 (y, y, y, w); }
|
||||
Vector4 Vector4::zyyw() const { return Vector4 (z, y, y, w); }
|
||||
Vector4 Vector4::wyyw() const { return Vector4 (w, y, y, w); }
|
||||
Vector4 Vector4::xzyw() const { return Vector4 (x, z, y, w); }
|
||||
Vector4 Vector4::yzyw() const { return Vector4 (y, z, y, w); }
|
||||
Vector4 Vector4::zzyw() const { return Vector4 (z, z, y, w); }
|
||||
Vector4 Vector4::wzyw() const { return Vector4 (w, z, y, w); }
|
||||
Vector4 Vector4::xwyw() const { return Vector4 (x, w, y, w); }
|
||||
Vector4 Vector4::ywyw() const { return Vector4 (y, w, y, w); }
|
||||
Vector4 Vector4::zwyw() const { return Vector4 (z, w, y, w); }
|
||||
Vector4 Vector4::wwyw() const { return Vector4 (w, w, y, w); }
|
||||
Vector4 Vector4::xxzw() const { return Vector4 (x, x, z, w); }
|
||||
Vector4 Vector4::yxzw() const { return Vector4 (y, x, z, w); }
|
||||
Vector4 Vector4::zxzw() const { return Vector4 (z, x, z, w); }
|
||||
Vector4 Vector4::wxzw() const { return Vector4 (w, x, z, w); }
|
||||
Vector4 Vector4::xyzw() const { return Vector4 (x, y, z, w); }
|
||||
Vector4 Vector4::yyzw() const { return Vector4 (y, y, z, w); }
|
||||
Vector4 Vector4::zyzw() const { return Vector4 (z, y, z, w); }
|
||||
Vector4 Vector4::wyzw() const { return Vector4 (w, y, z, w); }
|
||||
Vector4 Vector4::xzzw() const { return Vector4 (x, z, z, w); }
|
||||
Vector4 Vector4::yzzw() const { return Vector4 (y, z, z, w); }
|
||||
Vector4 Vector4::zzzw() const { return Vector4 (z, z, z, w); }
|
||||
Vector4 Vector4::wzzw() const { return Vector4 (w, z, z, w); }
|
||||
Vector4 Vector4::xwzw() const { return Vector4 (x, w, z, w); }
|
||||
Vector4 Vector4::ywzw() const { return Vector4 (y, w, z, w); }
|
||||
Vector4 Vector4::zwzw() const { return Vector4 (z, w, z, w); }
|
||||
Vector4 Vector4::wwzw() const { return Vector4 (w, w, z, w); }
|
||||
Vector4 Vector4::xxww() const { return Vector4 (x, x, w, w); }
|
||||
Vector4 Vector4::yxww() const { return Vector4 (y, x, w, w); }
|
||||
Vector4 Vector4::zxww() const { return Vector4 (z, x, w, w); }
|
||||
Vector4 Vector4::wxww() const { return Vector4 (w, x, w, w); }
|
||||
Vector4 Vector4::xyww() const { return Vector4 (x, y, w, w); }
|
||||
Vector4 Vector4::yyww() const { return Vector4 (y, y, w, w); }
|
||||
Vector4 Vector4::zyww() const { return Vector4 (z, y, w, w); }
|
||||
Vector4 Vector4::wyww() const { return Vector4 (w, y, w, w); }
|
||||
Vector4 Vector4::xzww() const { return Vector4 (x, z, w, w); }
|
||||
Vector4 Vector4::yzww() const { return Vector4 (y, z, w, w); }
|
||||
Vector4 Vector4::zzww() const { return Vector4 (z, z, w, w); }
|
||||
Vector4 Vector4::wzww() const { return Vector4 (w, z, w, w); }
|
||||
Vector4 Vector4::xwww() const { return Vector4 (x, w, w, w); }
|
||||
Vector4 Vector4::ywww() const { return Vector4 (y, w, w, w); }
|
||||
Vector4 Vector4::zwww() const { return Vector4 (z, w, w, w); }
|
||||
Vector4 Vector4::wwww() const { return Vector4 (w, w, w, w); }
|
||||
|
||||
|
||||
}; // namespace
|
||||
389
externals/g3dlite/debugAssert.cpp
vendored
Normal file
389
externals/g3dlite/debugAssert.cpp
vendored
Normal file
@@ -0,0 +1,389 @@
|
||||
/**
|
||||
@file debugAssert.cpp
|
||||
|
||||
Windows implementation of assertion routines.
|
||||
|
||||
@maintainer Morgan McGuire, graphics3d.com
|
||||
|
||||
@created 2001-08-26
|
||||
@edited 2009-06-02
|
||||
*/
|
||||
|
||||
#include "G3D/debugAssert.h"
|
||||
#include "G3D/platform.h"
|
||||
#ifdef G3D_WIN32
|
||||
#include <tchar.h>
|
||||
#endif
|
||||
#include "G3D/format.h"
|
||||
#include "G3D/prompt.h"
|
||||
#include <string>
|
||||
#include "G3D/debugPrintf.h"
|
||||
#include "G3D/Log.h"
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
// disable: "C++ exception handler used"
|
||||
# pragma warning (push)
|
||||
# pragma warning (disable : 4530)
|
||||
#endif
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace G3D { namespace _internal {
|
||||
|
||||
ConsolePrintHook _consolePrintHook;
|
||||
AssertionHook _debugHook = _handleDebugAssert_;
|
||||
AssertionHook _failureHook = _handleErrorCheck_;
|
||||
|
||||
#ifdef G3D_LINUX
|
||||
#if SOMEONE_MADE_THIS_USEFUL
|
||||
Display* x11Display = NULL;
|
||||
Window x11Window = 0;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef G3D_WIN32
|
||||
static void postToClipboard(const char *text) {
|
||||
if (OpenClipboard(NULL)) {
|
||||
HGLOBAL hMem = GlobalAlloc(GHND | GMEM_DDESHARE, strlen(text) + 1);
|
||||
if (hMem) {
|
||||
char *pMem = (char*)GlobalLock(hMem);
|
||||
strcpy(pMem, text);
|
||||
GlobalUnlock(hMem);
|
||||
|
||||
EmptyClipboard();
|
||||
SetClipboardData(CF_TEXT, hMem);
|
||||
}
|
||||
|
||||
CloseClipboard();
|
||||
GlobalFree(hMem);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
outTitle should be set before the call
|
||||
*/
|
||||
static void createErrorMessage(
|
||||
const char* expression,
|
||||
const std::string& message,
|
||||
const char* filename,
|
||||
int lineNumber,
|
||||
std::string& outTitle,
|
||||
std::string& outMessage) {
|
||||
|
||||
std::string le = "";
|
||||
const char* newline = "\n";
|
||||
|
||||
#ifdef G3D_WIN32
|
||||
newline = "\r\n";
|
||||
|
||||
// The last error value. (Which is preserved across the call).
|
||||
DWORD lastErr = GetLastError();
|
||||
|
||||
// The decoded message from FormatMessage
|
||||
LPTSTR formatMsg = NULL;
|
||||
|
||||
if (NULL == formatMsg) {
|
||||
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||||
FORMAT_MESSAGE_IGNORE_INSERTS |
|
||||
FORMAT_MESSAGE_FROM_SYSTEM,
|
||||
NULL,
|
||||
lastErr,
|
||||
0,
|
||||
(LPTSTR)&formatMsg,
|
||||
0,
|
||||
NULL);
|
||||
}
|
||||
|
||||
// Make sure the message got translated into something.
|
||||
LPTSTR realLastErr;
|
||||
if (NULL != formatMsg) {
|
||||
realLastErr = formatMsg;
|
||||
} else {
|
||||
realLastErr = _T("Last error code does not exist.");
|
||||
}
|
||||
|
||||
if (lastErr != 0) {
|
||||
le = G3D::format("Last Error (0x%08X): %s\r\n\r\n", lastErr, (LPCSTR)realLastErr);
|
||||
}
|
||||
|
||||
// Get rid of the allocated memory from FormatMessage.
|
||||
if (NULL != formatMsg) {
|
||||
LocalFree((LPVOID)formatMsg);
|
||||
}
|
||||
|
||||
char modulePath[MAX_PATH];
|
||||
GetModuleFileNameA(NULL, modulePath, MAX_PATH);
|
||||
|
||||
const char* moduleName = strrchr(modulePath, '\\');
|
||||
outTitle = outTitle + string(" - ") + string(moduleName ? (moduleName + 1) : modulePath);
|
||||
|
||||
#endif
|
||||
|
||||
// Build the message.
|
||||
outMessage =
|
||||
G3D::format("%s%s%sExpression: %s%s%s:%d%s%s%s",
|
||||
message.c_str(), newline, newline, expression, newline,
|
||||
filename, lineNumber, newline, newline, le.c_str());
|
||||
}
|
||||
|
||||
|
||||
bool _handleDebugAssert_(
|
||||
const char* expression,
|
||||
const std::string& message,
|
||||
const char* filename,
|
||||
int lineNumber,
|
||||
bool useGuiPrompt) {
|
||||
|
||||
std::string dialogTitle = "Assertion Failure";
|
||||
std::string dialogText = "";
|
||||
createErrorMessage(expression, message, filename, lineNumber, dialogTitle, dialogText);
|
||||
|
||||
#ifdef G3D_WIN32
|
||||
DWORD lastErr = GetLastError();
|
||||
postToClipboard(dialogText.c_str());
|
||||
debugPrintf("\n%s\n", dialogText.c_str());
|
||||
#endif
|
||||
|
||||
const int cBreak = 0;
|
||||
const int cIgnore = 1;
|
||||
const int cAbort = 2;
|
||||
|
||||
static const char* choices[] = {"Debug", "Ignore", "Exit"};
|
||||
|
||||
// Log the error
|
||||
Log::common()->print(std::string("\n**************************\n\n") + dialogTitle + "\n" + dialogText);
|
||||
|
||||
int result = G3D::prompt(dialogTitle.c_str(), dialogText.c_str(), (const char**)choices, 3, useGuiPrompt);
|
||||
|
||||
# ifdef G3D_WIN32
|
||||
// Put the incoming last error back.
|
||||
SetLastError(lastErr);
|
||||
# endif
|
||||
|
||||
switch (result) {
|
||||
// -1 shouldn't actually occur because it means
|
||||
// that we're in release mode.
|
||||
case -1:
|
||||
case cBreak:
|
||||
return true;
|
||||
break;
|
||||
|
||||
case cIgnore:
|
||||
return false;
|
||||
break;
|
||||
|
||||
case cAbort:
|
||||
exit(-1);
|
||||
break;
|
||||
}
|
||||
|
||||
// Should never get here
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool _handleErrorCheck_(
|
||||
const char* expression,
|
||||
const std::string& message,
|
||||
const char* filename,
|
||||
int lineNumber,
|
||||
bool useGuiPrompt) {
|
||||
|
||||
std::string dialogTitle = "Critical Error";
|
||||
std::string dialogText = "";
|
||||
|
||||
createErrorMessage(expression, message, filename, lineNumber, dialogTitle, dialogText);
|
||||
|
||||
// Log the error
|
||||
Log::common()->print(std::string("\n**************************\n\n") + dialogTitle + "\n" + dialogText);
|
||||
#ifdef G3D_WIN32
|
||||
DWORD lastErr = GetLastError();
|
||||
(void)lastErr;
|
||||
postToClipboard(dialogText.c_str());
|
||||
debugPrintf("\n%s\n", dialogText.c_str());
|
||||
#endif
|
||||
|
||||
static const char* choices[] = {"Ok"};
|
||||
|
||||
const std::string& m =
|
||||
std::string("An internal error has occured in this program and it will now close. "
|
||||
"The specific error is below. More information has been saved in \"") +
|
||||
Log::getCommonLogFilename() + "\".\n" + dialogText;
|
||||
|
||||
int result = G3D::prompt("Error", m.c_str(), (const char**)choices, 1, useGuiPrompt);
|
||||
(void)result;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
#ifdef G3D_WIN32
|
||||
static HCURSOR oldCursor;
|
||||
static RECT oldCursorRect;
|
||||
static POINT oldCursorPos;
|
||||
static int oldShowCursorCount;
|
||||
#endif
|
||||
|
||||
void _releaseInputGrab_() {
|
||||
#ifdef G3D_WIN32
|
||||
|
||||
GetCursorPos(&oldCursorPos);
|
||||
|
||||
// Stop hiding the cursor if the application hid it.
|
||||
oldShowCursorCount = ShowCursor(true) - 1;
|
||||
|
||||
if (oldShowCursorCount < -1) {
|
||||
for (int c = oldShowCursorCount; c < -1; ++c) {
|
||||
ShowCursor(true);
|
||||
}
|
||||
}
|
||||
|
||||
// Set the default cursor in case the application
|
||||
// set the cursor to NULL.
|
||||
oldCursor = GetCursor();
|
||||
SetCursor(LoadCursor(NULL, IDC_ARROW));
|
||||
|
||||
// Allow the cursor full access to the screen
|
||||
GetClipCursor(&oldCursorRect);
|
||||
ClipCursor(NULL);
|
||||
|
||||
#elif defined(G3D_LINUX)
|
||||
#if SOMEONE_MADE_THIS_USEFUL
|
||||
if (x11Display != NULL) {
|
||||
XUngrabPointer(x11Display, CurrentTime);
|
||||
XUngrabKeyboard(x11Display, CurrentTime);
|
||||
if (x11Window != 0) {
|
||||
//XUndefineCursor(x11Display, x11Window);
|
||||
// TODO: Note that we leak this cursor; it should be
|
||||
// freed in the restore code.
|
||||
Cursor c = XCreateFontCursor(x11Display, 68);
|
||||
XDefineCursor(x11Display, x11Window, c);
|
||||
}
|
||||
XSync(x11Display, false);
|
||||
XAllowEvents(x11Display, AsyncPointer, CurrentTime);
|
||||
XFlush(x11Display);
|
||||
}
|
||||
#endif
|
||||
#elif defined(G3D_OSX)
|
||||
// TODO: OS X
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void _restoreInputGrab_() {
|
||||
#ifdef G3D_WIN32
|
||||
|
||||
// Restore the old clipping region
|
||||
ClipCursor(&oldCursorRect);
|
||||
|
||||
SetCursorPos(oldCursorPos.x, oldCursorPos.y);
|
||||
|
||||
// Restore the old cursor
|
||||
SetCursor(oldCursor);
|
||||
|
||||
// Restore old visibility count
|
||||
if (oldShowCursorCount < 0) {
|
||||
for (int c = 0; c > oldShowCursorCount; --c) {
|
||||
ShowCursor(false);
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined(G3D_LINUX)
|
||||
// TODO: Linux
|
||||
#elif defined(G3D_OSX)
|
||||
// TODO: OS X
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
}; // internal namespace
|
||||
|
||||
void setAssertionHook(AssertionHook hook) {
|
||||
G3D::_internal::_debugHook = hook;
|
||||
}
|
||||
|
||||
AssertionHook assertionHook() {
|
||||
return G3D::_internal::_debugHook;
|
||||
}
|
||||
|
||||
void setFailureHook(AssertionHook hook) {
|
||||
G3D::_internal::_failureHook = hook;
|
||||
}
|
||||
|
||||
AssertionHook failureHook() {
|
||||
return G3D::_internal::_failureHook;
|
||||
}
|
||||
|
||||
|
||||
void setConsolePrintHook(ConsolePrintHook h) {
|
||||
G3D::_internal::_consolePrintHook = h;
|
||||
}
|
||||
|
||||
ConsolePrintHook consolePrintHook() {
|
||||
return G3D::_internal::_consolePrintHook;
|
||||
}
|
||||
|
||||
|
||||
std::string __cdecl debugPrint(const std::string& s) {
|
||||
# ifdef G3D_WIN32
|
||||
const int MAX_STRING_LEN = 1024;
|
||||
|
||||
// Windows can't handle really long strings sent to
|
||||
// the console, so we break the string.
|
||||
if (s.size() < MAX_STRING_LEN) {
|
||||
OutputDebugStringA(s.c_str());
|
||||
} else {
|
||||
for (unsigned int i = 0; i < s.size(); i += MAX_STRING_LEN) {
|
||||
std::string sub = s.substr(i, MAX_STRING_LEN);
|
||||
OutputDebugStringA(sub.c_str());
|
||||
}
|
||||
}
|
||||
# else
|
||||
fprintf(stderr, "%s", s.c_str());
|
||||
fflush(stderr);
|
||||
# endif
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
std::string __cdecl debugPrintf(const char* fmt ...) {
|
||||
va_list argList;
|
||||
va_start(argList, fmt);
|
||||
std::string s = G3D::vformat(fmt, argList);
|
||||
va_end(argList);
|
||||
|
||||
return debugPrint(s);
|
||||
// return debugPrint(consolePrint(s));
|
||||
}
|
||||
|
||||
std::string consolePrint(const std::string& s) {
|
||||
FILE* L = Log::common()->getFile();
|
||||
fprintf(L, "%s", s.c_str());
|
||||
|
||||
if (consolePrintHook()) {
|
||||
consolePrintHook()(s);
|
||||
}
|
||||
|
||||
fflush(L);
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
std::string __cdecl consolePrintf(const char* fmt ...) {
|
||||
va_list argList;
|
||||
va_start(argList, fmt);
|
||||
std::string s = G3D::vformat(fmt, argList);
|
||||
va_end(argList);
|
||||
|
||||
return consolePrint(s);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# pragma warning (pop)
|
||||
#endif
|
||||
1165
externals/g3dlite/fileutils.cpp
vendored
Normal file
1165
externals/g3dlite/fileutils.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
164
externals/g3dlite/format.cpp
vendored
Normal file
164
externals/g3dlite/format.cpp
vendored
Normal file
@@ -0,0 +1,164 @@
|
||||
/**
|
||||
@file format.cpp
|
||||
|
||||
@author Morgan McGuire, graphics3d.com
|
||||
|
||||
@created 2000-09-09
|
||||
@edited 2006-08-14
|
||||
*/
|
||||
|
||||
#include "G3D/format.h"
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/System.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
// disable: "C++ exception handler used"
|
||||
# pragma warning (push)
|
||||
# pragma warning (disable : 4530)
|
||||
#endif // _MSC_VER
|
||||
|
||||
// If your platform does not have vsnprintf, you can find a
|
||||
// implementation at http://www.ijs.si/software/snprintf/
|
||||
|
||||
namespace G3D {
|
||||
|
||||
std::string __cdecl format(const char* fmt,...) {
|
||||
va_list argList;
|
||||
va_start(argList,fmt);
|
||||
std::string result = vformat(fmt, argList);
|
||||
va_end(argList);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1300)
|
||||
// Both MSVC seems to use the non-standard vsnprintf
|
||||
// so we are using vscprintf to determine buffer size, however
|
||||
// only MSVC7 and up headers include vscprintf for some reason.
|
||||
std::string vformat(const char *fmt, va_list argPtr) {
|
||||
// We draw the line at a 1MB string.
|
||||
const int maxSize = 1000000;
|
||||
|
||||
// If the string is less than 161 characters,
|
||||
// allocate it on the stack because this saves
|
||||
// the malloc/free time.
|
||||
const int bufSize = 161;
|
||||
char stackBuffer[bufSize];
|
||||
|
||||
// MSVC does not support va_copy
|
||||
int actualSize = _vscprintf(fmt, argPtr) + 1;
|
||||
|
||||
if (actualSize > bufSize) {
|
||||
|
||||
// Now use the heap.
|
||||
char* heapBuffer = NULL;
|
||||
|
||||
if (actualSize < maxSize) {
|
||||
|
||||
heapBuffer = (char*)System::malloc(maxSize + 1);
|
||||
_vsnprintf(heapBuffer, maxSize, fmt, argPtr);
|
||||
heapBuffer[maxSize] = '\0';
|
||||
} else {
|
||||
heapBuffer = (char*)System::malloc(actualSize);
|
||||
vsprintf(heapBuffer, fmt, argPtr);
|
||||
}
|
||||
|
||||
std::string formattedString(heapBuffer);
|
||||
System::free(heapBuffer);
|
||||
return formattedString;
|
||||
} else {
|
||||
|
||||
vsprintf(stackBuffer, fmt, argPtr);
|
||||
return std::string(stackBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined(_MSC_VER) && (_MSC_VER < 1300)
|
||||
|
||||
std::string vformat(const char *fmt, va_list argPtr) {
|
||||
// We draw the line at a 1MB string.
|
||||
const int maxSize = 1000000;
|
||||
|
||||
// If the string is less than 161 characters,
|
||||
// allocate it on the stack because this saves
|
||||
// the malloc/free time.
|
||||
const int bufSize = 161;
|
||||
char stackBuffer[bufSize];
|
||||
|
||||
// MSVC6 doesn't support va_copy, however it also seems to compile
|
||||
// correctly if we just pass our argument list along. Note that
|
||||
// this whole code block is only compiled if we're on MSVC6 anyway
|
||||
int actualWritten = _vsnprintf(stackBuffer, bufSize, fmt, argPtr);
|
||||
|
||||
// Not a big enough buffer, bufSize characters written
|
||||
if (actualWritten == -1) {
|
||||
|
||||
int heapSize = 512;
|
||||
double powSize = 1.0;
|
||||
char* heapBuffer = (char*)System::malloc(heapSize);
|
||||
|
||||
while ((_vsnprintf(heapBuffer, heapSize, fmt, argPtr) == -1) &&
|
||||
(heapSize < maxSize)) {
|
||||
|
||||
heapSize = iCeil(heapSize * ::pow((double)2.0, powSize++));
|
||||
heapBuffer = (char*)System::realloc(heapBuffer, heapSize);
|
||||
}
|
||||
|
||||
heapBuffer[heapSize-1] = '\0';
|
||||
|
||||
std::string heapString(heapBuffer);
|
||||
System::free(heapBuffer);
|
||||
|
||||
return heapString;
|
||||
} else {
|
||||
|
||||
return std::string(stackBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
// glibc 2.1 has been updated to the C99 standard
|
||||
std::string vformat(const char* fmt, va_list argPtr) {
|
||||
// If the string is less than 161 characters,
|
||||
// allocate it on the stack because this saves
|
||||
// the malloc/free time. The number 161 is chosen
|
||||
// to support two lines of text on an 80 character
|
||||
// console (plus the null terminator).
|
||||
const int bufSize = 161;
|
||||
char stackBuffer[bufSize];
|
||||
|
||||
va_list argPtrCopy;
|
||||
va_copy(argPtrCopy, argPtr);
|
||||
int numChars = vsnprintf(stackBuffer, bufSize, fmt, argPtrCopy);
|
||||
va_end(argPtrCopy);
|
||||
|
||||
if (numChars >= bufSize) {
|
||||
// We didn't allocate a big enough string.
|
||||
char* heapBuffer = (char*)System::malloc((numChars + 1) * sizeof(char));
|
||||
|
||||
debugAssert(heapBuffer);
|
||||
int numChars2 = vsnprintf(heapBuffer, numChars + 1, fmt, argPtr);
|
||||
debugAssert(numChars2 == numChars);
|
||||
(void)numChars2;
|
||||
|
||||
std::string result(heapBuffer);
|
||||
|
||||
System::free(heapBuffer);
|
||||
|
||||
return result;
|
||||
|
||||
} else {
|
||||
|
||||
return std::string(stackBuffer);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# pragma warning (pop)
|
||||
#endif
|
||||
204
externals/g3dlite/g3dfnmatch.cpp
vendored
Normal file
204
externals/g3dlite/g3dfnmatch.cpp
vendored
Normal file
@@ -0,0 +1,204 @@
|
||||
/*-
|
||||
* Copyright (c) 1992, 1993
|
||||
*The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
*This product includes software developed by the University of
|
||||
*California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
|
||||
*
|
||||
*@(#)fnmatch.h8.1 (Berkeley) 6/2/93
|
||||
*
|
||||
* From FreeBSD fnmatch.h 1.7
|
||||
* $Id: g3dfnmatch.cpp,v 1.2 2010/02/06 10:03:24 corey_taylor Exp $
|
||||
*/
|
||||
#include "G3D/g3dfnmatch.h"
|
||||
|
||||
#ifdef G3D_WIN32
|
||||
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
namespace G3D {
|
||||
|
||||
#define EOS '\0'
|
||||
|
||||
static const char *rangematch(const char *, char, int);
|
||||
|
||||
int g3dfnmatch(const char *pattern, const char *string, int flags)
|
||||
{
|
||||
const char *stringstart;
|
||||
char c, test;
|
||||
|
||||
for (stringstart = string;;)
|
||||
switch (c = *pattern++) {
|
||||
case EOS:
|
||||
if ((flags & FNM_LEADING_DIR) && *string == '/')
|
||||
return (0);
|
||||
return (*string == EOS ? 0 : FNM_NOMATCH);
|
||||
case '?':
|
||||
if (*string == EOS)
|
||||
return (FNM_NOMATCH);
|
||||
if (*string == '/' && (flags & FNM_PATHNAME))
|
||||
return (FNM_NOMATCH);
|
||||
if (*string == '.' && (flags & FNM_PERIOD) &&
|
||||
(string == stringstart ||
|
||||
((flags & FNM_PATHNAME) && *(string - 1) == '/')))
|
||||
return (FNM_NOMATCH);
|
||||
++string;
|
||||
break;
|
||||
case '*':
|
||||
c = *pattern;
|
||||
/* Collapse multiple stars. */
|
||||
while (c == '*')
|
||||
c = *++pattern;
|
||||
|
||||
if (*string == '.' && (flags & FNM_PERIOD) &&
|
||||
(string == stringstart ||
|
||||
((flags & FNM_PATHNAME) && *(string - 1) == '/')))
|
||||
return (FNM_NOMATCH);
|
||||
|
||||
/* Optimize for pattern with * at end or before /. */
|
||||
if (c == EOS)
|
||||
if (flags & FNM_PATHNAME)
|
||||
return ((flags & FNM_LEADING_DIR) ||
|
||||
strchr(string, '/') == NULL ?
|
||||
0 : FNM_NOMATCH);
|
||||
else
|
||||
return (0);
|
||||
else if (c == '/' && flags & FNM_PATHNAME) {
|
||||
if ((string = strchr(string, '/')) == NULL)
|
||||
return (FNM_NOMATCH);
|
||||
break;
|
||||
}
|
||||
|
||||
/* General case, use recursion. */
|
||||
while ((test = *string) != EOS) {
|
||||
if (!rangematch(pattern, *string, flags & ~FNM_PERIOD))
|
||||
return (0);
|
||||
if (test == '/' && flags & FNM_PATHNAME)
|
||||
break;
|
||||
++string;
|
||||
}
|
||||
return (FNM_NOMATCH);
|
||||
case '[':
|
||||
if (*string == EOS)
|
||||
return (FNM_NOMATCH);
|
||||
if (*string == '/' && flags & FNM_PATHNAME)
|
||||
return (FNM_NOMATCH);
|
||||
if ((pattern =
|
||||
rangematch(pattern, *string, flags)) == NULL)
|
||||
return (FNM_NOMATCH);
|
||||
++string;
|
||||
break;
|
||||
case '\\':
|
||||
if (!(flags & FNM_NOESCAPE)) {
|
||||
if ((c = *pattern++) == EOS) {
|
||||
c = '\\';
|
||||
--pattern;
|
||||
}
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
default:
|
||||
if (c == *string)
|
||||
;
|
||||
else if ((flags & FNM_CASEFOLD) &&
|
||||
(tolower((unsigned char)c) ==
|
||||
tolower((unsigned char)*string)))
|
||||
;
|
||||
else if ((flags & FNM_PREFIX_DIRS) && *string == EOS &&
|
||||
((c == '/' && string != stringstart) ||
|
||||
(string == stringstart+1 && *stringstart == '/')))
|
||||
return (0);
|
||||
else
|
||||
return (FNM_NOMATCH);
|
||||
string++;
|
||||
break;
|
||||
}
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
static const char *
|
||||
rangematch(const char *pattern, char test, int flags)
|
||||
{
|
||||
int negate, ok;
|
||||
char c, c2;
|
||||
|
||||
/*
|
||||
* A bracket expression starting with an unquoted circumflex
|
||||
* character produces unspecified results (IEEE 1003.2-1992,
|
||||
* 3.13.2). This implementation treats it like '!', for
|
||||
* consistency with the regular expression syntax.
|
||||
* J.T. Conklin (conklin@ngai.kaleida.com)
|
||||
*/
|
||||
if ( (negate = (*pattern == '!' || *pattern == '^')) )
|
||||
++pattern;
|
||||
|
||||
if (flags & FNM_CASEFOLD)
|
||||
test = tolower((unsigned char)test);
|
||||
|
||||
for (ok = 0; (c = *pattern++) != ']';) {
|
||||
if (c == '\\' && !(flags & FNM_NOESCAPE))
|
||||
c = *pattern++;
|
||||
if (c == EOS)
|
||||
return (NULL);
|
||||
|
||||
if (flags & FNM_CASEFOLD)
|
||||
c = tolower((unsigned char)c);
|
||||
|
||||
if (*pattern == '-'
|
||||
&& (c2 = *(pattern+1)) != EOS && c2 != ']') {
|
||||
pattern += 2;
|
||||
if (c2 == '\\' && !(flags & FNM_NOESCAPE))
|
||||
c2 = *pattern++;
|
||||
if (c2 == EOS)
|
||||
return (NULL);
|
||||
|
||||
if (flags & FNM_CASEFOLD)
|
||||
c2 = tolower((unsigned char)c2);
|
||||
|
||||
if ((unsigned char)c <= (unsigned char)test &&
|
||||
(unsigned char)test <= (unsigned char)c2)
|
||||
ok = 1;
|
||||
} else if (c == test)
|
||||
ok = 1;
|
||||
}
|
||||
return (ok == negate ? NULL : pattern);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
namespace G3D {
|
||||
int g3dfnmatch(const char * a, const char *b, int c) {
|
||||
return fnmatch(a, b, c);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
108
externals/g3dlite/g3dmath.cpp
vendored
Normal file
108
externals/g3dlite/g3dmath.cpp
vendored
Normal file
@@ -0,0 +1,108 @@
|
||||
/**
|
||||
@file g3dmath.cpp
|
||||
|
||||
@author Morgan McGuire, graphics3d.com
|
||||
|
||||
@created 2001-06-02
|
||||
@edited 2004-02-24
|
||||
*/
|
||||
|
||||
#include "G3D/g3dmath.h"
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
namespace G3D {
|
||||
|
||||
float gaussRandom(float mean, float stdev) {
|
||||
|
||||
// Using Box-Mueller method from http://www.taygeta.com/random/gaussian.html
|
||||
// Modified to specify standard deviation and mean of distribution
|
||||
float w, x1, x2;
|
||||
|
||||
// Loop until w is less than 1 so that log(w) is negative
|
||||
do {
|
||||
x1 = uniformRandom(-1.0, 1.0);
|
||||
x2 = uniformRandom(-1.0, 1.0);
|
||||
|
||||
w = float(square(x1) + square(x2));
|
||||
} while (w > 1.0f);
|
||||
|
||||
// Transform to gassian distribution
|
||||
// Multiply by sigma (stdev ^ 2) and add mean.
|
||||
return x2 * (float)square(stdev) * sqrtf((-2.0f * logf(w) ) / w) + mean;
|
||||
}
|
||||
|
||||
/**
|
||||
This value should not be tested against directly, instead
|
||||
G3D::isNan() and G3D::isFinite() will return reliable results. */
|
||||
double inf() {
|
||||
return std::numeric_limits<double>::infinity();
|
||||
}
|
||||
|
||||
bool isNaN(float x) {
|
||||
static const float n = nan();
|
||||
return memcmp(&x, &n, sizeof(float)) == 0;
|
||||
}
|
||||
|
||||
bool isNaN(double x) {
|
||||
static const double n = nan();
|
||||
return memcmp(&x, &n, sizeof(double)) == 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
This value should not be tested against directly, instead
|
||||
G3D::isNan() and G3D::isFinite() will return reliable results. */
|
||||
float finf() {
|
||||
return std::numeric_limits<float>::infinity();
|
||||
}
|
||||
|
||||
/** This value should not be tested against directly, instead
|
||||
G3D::isNan() and G3D::isFinite() will return reliable results. */
|
||||
double nan() {
|
||||
// double is a standard type and should have quiet NaN
|
||||
return std::numeric_limits<double>::quiet_NaN();
|
||||
}
|
||||
|
||||
float fnan() {
|
||||
// double is a standard type and should have quiet NaN
|
||||
return std::numeric_limits<float>::quiet_NaN();
|
||||
}
|
||||
|
||||
|
||||
int highestBit(uint32 x) {
|
||||
// Binary search.
|
||||
int base = 0;
|
||||
|
||||
if (x & 0xffff0000) {
|
||||
base = 16;
|
||||
x >>= 16;
|
||||
}
|
||||
if (x & 0x0000ff00) {
|
||||
base += 8;
|
||||
x >>= 8;
|
||||
}
|
||||
if (x & 0x000000f0) {
|
||||
base += 4;
|
||||
x >>= 4;
|
||||
}
|
||||
|
||||
static const int lut[] = {-1,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3};
|
||||
return base + lut[x];
|
||||
}
|
||||
|
||||
|
||||
int iRandom(int low, int high) {
|
||||
int r = iFloor(low + (high - low + 1) * (double)rand() / RAND_MAX);
|
||||
|
||||
// There is a *very small* chance of generating
|
||||
// a number larger than high.
|
||||
if (r > high) {
|
||||
return high;
|
||||
} else {
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
729
externals/g3dlite/prompt.cpp
vendored
Normal file
729
externals/g3dlite/prompt.cpp
vendored
Normal file
@@ -0,0 +1,729 @@
|
||||
/**
|
||||
@file prompt.cpp
|
||||
|
||||
@author Morgan McGuire, http://graphics.cs.williams.edu
|
||||
@cite Windows dialog interface by Max McGuire, mmcguire@ironlore.com
|
||||
@cite Font setting code by Kurt Miller, kurt@flipcode.com
|
||||
|
||||
@created 2000-08-26
|
||||
@edited 2005-01-14
|
||||
*/
|
||||
|
||||
#include "G3D/prompt.h"
|
||||
#include "G3D/platform.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef G3D_WIN32
|
||||
# include <sstream>
|
||||
# include <conio.h>
|
||||
#else
|
||||
# define _getch getchar
|
||||
#endif
|
||||
|
||||
#ifdef G3D_OSX
|
||||
|
||||
/*#ifdef __LP64__
|
||||
# undef __LP64__
|
||||
#endif
|
||||
*/
|
||||
|
||||
# include <Carbon/Carbon.h>
|
||||
|
||||
/*
|
||||
#ifdef G3D_64BIT
|
||||
# define __LP64__
|
||||
#endif
|
||||
*/
|
||||
|
||||
#endif
|
||||
|
||||
namespace G3D {
|
||||
|
||||
#ifdef G3D_WIN32
|
||||
|
||||
namespace _internal {
|
||||
/**
|
||||
Generic Win32 dialog facility.
|
||||
@author Max McGuire
|
||||
*/
|
||||
class DialogTemplate {
|
||||
public:
|
||||
|
||||
DialogTemplate(LPCSTR caption, DWORD style,
|
||||
int x, int y, int w, int h,
|
||||
LPCSTR font = NULL, WORD fontSize = 8) {
|
||||
|
||||
usedBufferLength = sizeof(DLGTEMPLATE);
|
||||
totalBufferLength = usedBufferLength;
|
||||
|
||||
dialogTemplate = (DLGTEMPLATE*)malloc(totalBufferLength);
|
||||
|
||||
dialogTemplate->style = style;
|
||||
|
||||
if (font != NULL) {
|
||||
dialogTemplate->style |= DS_SETFONT;
|
||||
}
|
||||
|
||||
dialogTemplate->x = (short)x;
|
||||
dialogTemplate->y = (short)y;
|
||||
dialogTemplate->cx = (short)w;
|
||||
dialogTemplate->cy = (short)h;
|
||||
dialogTemplate->cdit = 0;
|
||||
|
||||
dialogTemplate->dwExtendedStyle = 0;
|
||||
|
||||
// The dialog box doesn't have a menu or a special class
|
||||
AppendData("\0", 2);
|
||||
AppendData("\0", 2);
|
||||
|
||||
// Add the dialog's caption to the template
|
||||
|
||||
AppendString(caption);
|
||||
|
||||
if (font != NULL) {
|
||||
AppendData(&fontSize, sizeof(WORD));
|
||||
AppendString(font);
|
||||
}
|
||||
}
|
||||
|
||||
void AddComponent(LPCSTR type, LPCSTR caption, DWORD style, DWORD exStyle, int x, int y, int w, int h, WORD id) {
|
||||
|
||||
DLGITEMTEMPLATE item;
|
||||
|
||||
item.style = style;
|
||||
item.x = (short)x;
|
||||
item.y = (short)y;
|
||||
item.cx = (short)w;
|
||||
item.cy = (short)h;
|
||||
item.id = id;
|
||||
|
||||
item.dwExtendedStyle = exStyle;
|
||||
|
||||
AppendData(&item, sizeof(DLGITEMTEMPLATE));
|
||||
|
||||
AppendString(type);
|
||||
AppendString(caption);
|
||||
|
||||
WORD creationDataLength = 0;
|
||||
AppendData(&creationDataLength, sizeof(WORD));
|
||||
|
||||
// Increment the component count
|
||||
dialogTemplate->cdit++;
|
||||
|
||||
}
|
||||
|
||||
|
||||
void AddButton(LPCSTR caption, DWORD style, DWORD exStyle, int x, int y, int w, int h, WORD id) {
|
||||
|
||||
AddStandardComponent(0x0080, caption, style, exStyle, x, y, w, h, id);
|
||||
|
||||
WORD creationDataLength = 0;
|
||||
AppendData(&creationDataLength, sizeof(WORD));
|
||||
|
||||
}
|
||||
|
||||
|
||||
void AddEditBox(LPCSTR caption, DWORD style, DWORD exStyle, int x, int y, int w, int h, WORD id) {
|
||||
|
||||
AddStandardComponent(0x0081, caption, style, exStyle, x, y, w, h, id);
|
||||
|
||||
WORD creationDataLength = 0;
|
||||
AppendData(&creationDataLength, sizeof(WORD));
|
||||
|
||||
}
|
||||
|
||||
|
||||
void AddStatic(LPCSTR caption, DWORD style, DWORD exStyle, int x, int y, int w, int h, WORD id) {
|
||||
|
||||
AddStandardComponent(0x0082, caption, style, exStyle, x, y, w, h, id);
|
||||
|
||||
WORD creationDataLength = 0;
|
||||
AppendData(&creationDataLength, sizeof(WORD));
|
||||
|
||||
}
|
||||
|
||||
|
||||
void AddListBox(LPCSTR caption, DWORD style, DWORD exStyle, int x, int y, int w, int h, WORD id) {
|
||||
|
||||
AddStandardComponent(0x0083, caption, style, exStyle, x, y, w, h, id);
|
||||
|
||||
WORD creationDataLength = sizeof(WORD) + 5 * sizeof(WCHAR);
|
||||
AppendData(&creationDataLength, sizeof(WORD));
|
||||
|
||||
AppendString("TEST");
|
||||
|
||||
}
|
||||
|
||||
|
||||
void AddScrollBar(LPCSTR caption, DWORD style, DWORD exStyle, int x, int y, int w, int h, WORD id) {
|
||||
|
||||
AddStandardComponent(0x0084, caption, style, exStyle, x, y, w, h, id);
|
||||
|
||||
WORD creationDataLength = 0;
|
||||
AppendData(&creationDataLength, sizeof(WORD));
|
||||
|
||||
}
|
||||
|
||||
|
||||
void AddComboBox(LPCSTR caption, DWORD style, DWORD exStyle, int x, int y, int w, int h, WORD id) {
|
||||
|
||||
AddStandardComponent(0x0085, caption, style, exStyle, x, y, w, h, id);
|
||||
|
||||
WORD creationDataLength = 0;
|
||||
AppendData(&creationDataLength, sizeof(WORD));
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* Returns a pointer to the Win32 dialog template which the object
|
||||
* represents. This pointer may become invalid if additional components
|
||||
* are added to the template.
|
||||
*
|
||||
*/
|
||||
operator const DLGTEMPLATE*() const {
|
||||
return dialogTemplate;
|
||||
}
|
||||
|
||||
virtual ~DialogTemplate() {
|
||||
free(dialogTemplate);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
void AddStandardComponent(WORD type, LPCSTR caption, DWORD style, DWORD exStyle,
|
||||
int x, int y, int w, int h, WORD id, LPSTR font = NULL, WORD fontSize = 8) {
|
||||
|
||||
DLGITEMTEMPLATE item;
|
||||
|
||||
// DWORD align the beginning of the component data
|
||||
|
||||
AlignData(sizeof(DWORD));
|
||||
|
||||
item.style = style;
|
||||
if (font != NULL) {
|
||||
item.style |= DS_SETFONT;
|
||||
}
|
||||
item.x = (short)x;
|
||||
item.y = (short)y;
|
||||
item.cx = (short)w;
|
||||
item.cy = (short)h;
|
||||
item.id = id;
|
||||
|
||||
item.dwExtendedStyle = exStyle;
|
||||
|
||||
AppendData(&item, sizeof(DLGITEMTEMPLATE));
|
||||
|
||||
WORD preType = 0xFFFF;
|
||||
|
||||
AppendData(&preType, sizeof(WORD));
|
||||
AppendData(&type, sizeof(WORD));
|
||||
|
||||
AppendString(caption);
|
||||
|
||||
if (font != NULL) {
|
||||
AppendData(&fontSize, sizeof(WORD));
|
||||
AppendString(font);
|
||||
}
|
||||
|
||||
// Increment the component count
|
||||
dialogTemplate->cdit++;
|
||||
}
|
||||
|
||||
|
||||
void AlignData(int size) {
|
||||
|
||||
int paddingSize = usedBufferLength % size;
|
||||
|
||||
if (paddingSize != 0) {
|
||||
EnsureSpace(paddingSize);
|
||||
usedBufferLength += paddingSize;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void AppendString(LPCSTR string) {
|
||||
|
||||
int length = MultiByteToWideChar(CP_ACP, 0, string, -1, NULL, 0);
|
||||
|
||||
WCHAR* wideString = (WCHAR*)malloc(sizeof(WCHAR) * length);
|
||||
MultiByteToWideChar(CP_ACP, 0, string, -1, wideString, length);
|
||||
|
||||
AppendData(wideString, length * sizeof(WCHAR));
|
||||
free(wideString);
|
||||
|
||||
}
|
||||
|
||||
void AppendData(const void* data, int dataLength) {
|
||||
|
||||
EnsureSpace(dataLength);
|
||||
|
||||
memcpy((char*)dialogTemplate + usedBufferLength, data, dataLength);
|
||||
usedBufferLength += dataLength;
|
||||
|
||||
}
|
||||
|
||||
void EnsureSpace(int length) {
|
||||
if (length + usedBufferLength > totalBufferLength) {
|
||||
totalBufferLength += length * 2;
|
||||
|
||||
void* newBuffer = malloc(totalBufferLength);
|
||||
memcpy(newBuffer, dialogTemplate, usedBufferLength);
|
||||
|
||||
free(dialogTemplate);
|
||||
dialogTemplate = (DLGTEMPLATE*)newBuffer;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
DLGTEMPLATE* dialogTemplate;
|
||||
|
||||
int totalBufferLength;
|
||||
int usedBufferLength;
|
||||
|
||||
};
|
||||
|
||||
|
||||
struct PromptParams {
|
||||
const char* message;
|
||||
const char* title;
|
||||
};
|
||||
|
||||
/**
|
||||
* Constants for controls.
|
||||
*/
|
||||
#define IDC_MESSAGE 1000
|
||||
#define IDC_BUTTON0 2000
|
||||
|
||||
INT_PTR CALLBACK PromptDlgProc(HWND hDlg, UINT msg,
|
||||
WPARAM wParam, LPARAM lParam) {
|
||||
switch(msg) {
|
||||
case WM_INITDIALOG:
|
||||
{
|
||||
PromptParams *params = (PromptParams*)lParam;
|
||||
::SetWindowTextA(::GetDlgItem(hDlg, IDC_MESSAGE), params->message);
|
||||
|
||||
::SetFocus(::GetDlgItem(hDlg, IDC_BUTTON0));
|
||||
|
||||
SetWindowTextA(hDlg, params->title);
|
||||
|
||||
HFONT hfont =
|
||||
CreateFontA(16, 0, 0, 0, FW_NORMAL,
|
||||
FALSE, FALSE, FALSE,
|
||||
ANSI_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,
|
||||
PROOF_QUALITY, FIXED_PITCH | FF_MODERN, "Courier New");
|
||||
|
||||
SendDlgItemMessage(hDlg, IDC_MESSAGE, WM_SETFONT, (WPARAM)hfont, MAKELPARAM(TRUE,0));
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
case WM_COMMAND:
|
||||
{
|
||||
int choiceNumber = LOWORD(wParam) - IDC_BUTTON0;
|
||||
if ((choiceNumber >= 0) && (choiceNumber < 10)) {
|
||||
EndDialog(hDlg, choiceNumber);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case WM_NCDESTROY:
|
||||
// Under SDL 1.2.6 we get a NCDESTROY message for no reason and the
|
||||
// window is immediately closed. This is here to debug the problem.
|
||||
(void)0;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
}; // namespace _internal
|
||||
|
||||
|
||||
using namespace _internal;
|
||||
|
||||
/**
|
||||
* Show a dialog prompt.
|
||||
*/
|
||||
static int guiPrompt(
|
||||
const char* windowTitle,
|
||||
const char* prompt,
|
||||
const char** choice,
|
||||
int numChoices) {
|
||||
|
||||
int width = 280;
|
||||
int height = 128;
|
||||
|
||||
const int buttonSpacing = 2;
|
||||
const int buttonWidth =
|
||||
(width - buttonSpacing * 2 -
|
||||
buttonSpacing * (numChoices - 1)) / numChoices;
|
||||
const int buttonHeight = 13;
|
||||
|
||||
|
||||
DialogTemplate dialogTemplate(
|
||||
windowTitle,
|
||||
WS_CAPTION | DS_CENTER | WS_SYSMENU,
|
||||
10, 10, width, height,
|
||||
"Tahoma");
|
||||
|
||||
dialogTemplate.AddEditBox(
|
||||
"Edit", WS_VISIBLE | ES_READONLY | ES_OEMCONVERT | ES_MULTILINE | WS_TABSTOP, WS_EX_STATICEDGE,
|
||||
2, 2, width - 4, height - buttonHeight - 7, IDC_MESSAGE);
|
||||
|
||||
int i;
|
||||
for (i = 0; i < numChoices; i++) {
|
||||
|
||||
int x = buttonSpacing + i * (buttonWidth + buttonSpacing);
|
||||
int y = height - buttonHeight - buttonSpacing;
|
||||
|
||||
dialogTemplate.AddButton(choice[i], WS_VISIBLE | WS_TABSTOP, 0,
|
||||
x, y, buttonWidth, buttonHeight, IDC_BUTTON0 + (WORD)i);
|
||||
|
||||
}
|
||||
|
||||
// Convert all single \n characters to \r\n for proper printing
|
||||
int strLen = 0;
|
||||
const char* pStr = prompt;
|
||||
|
||||
while (*pStr != '\0') {
|
||||
if ((*pStr == '\n') && (pStr != prompt)) {
|
||||
if (*(pStr - 1) != '\r') {
|
||||
++strLen;
|
||||
}
|
||||
}
|
||||
++strLen;
|
||||
++pStr;
|
||||
}
|
||||
|
||||
char* newStr = (char*)malloc(strLen + 1);
|
||||
|
||||
const char* pStr2 = prompt;
|
||||
char* pNew = newStr;
|
||||
|
||||
while (*pStr2 != '\0') {
|
||||
if ((*pStr2 == '\n') && (pStr2 != prompt)) {
|
||||
if (*(pStr2 - 1) != '\r') {
|
||||
*pNew = '\r';
|
||||
++pNew;
|
||||
}
|
||||
}
|
||||
*pNew = *pStr2;
|
||||
++pNew;
|
||||
++pStr2;
|
||||
}
|
||||
|
||||
*pNew = '\0';
|
||||
|
||||
PromptParams params;
|
||||
params.message = newStr;;
|
||||
params.title = windowTitle;
|
||||
|
||||
HMODULE module = GetModuleHandle(0);
|
||||
int ret = DialogBoxIndirectParam(module, dialogTemplate, NULL, (DLGPROC) PromptDlgProc, (DWORD)¶ms);
|
||||
|
||||
free(newStr);
|
||||
|
||||
/*
|
||||
For debugging when DialogBoxIndirectParam fails:
|
||||
|
||||
// The last error value. (Which is preserved across the call).
|
||||
DWORD lastErr = GetLastError();
|
||||
|
||||
// The decoded message from FormatMessage
|
||||
LPTSTR formatMsg = NULL;
|
||||
|
||||
if (NULL == formatMsg) {
|
||||
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||||
FORMAT_MESSAGE_IGNORE_INSERTS |
|
||||
FORMAT_MESSAGE_FROM_SYSTEM,
|
||||
NULL,
|
||||
lastErr,
|
||||
0,
|
||||
(LPTSTR)&formatMsg,
|
||||
0,
|
||||
NULL);
|
||||
}
|
||||
|
||||
// Make sure the message got translated into something.
|
||||
LPTSTR realLastErr;
|
||||
if (NULL != formatMsg) {
|
||||
realLastErr = formatMsg;
|
||||
} else {
|
||||
realLastErr = "Last error code does not exist.";
|
||||
}
|
||||
|
||||
// Get rid of the allocated memory from FormatMessage.
|
||||
if (NULL != formatMsg) {
|
||||
LocalFree((LPVOID)formatMsg);
|
||||
}
|
||||
*/
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* Show a prompt on stdout
|
||||
*/
|
||||
static int textPrompt(
|
||||
const char* windowTitle,
|
||||
const char* prompt,
|
||||
const char** choice,
|
||||
int numChoices) {
|
||||
|
||||
printf("\n___________________________________________________\n");
|
||||
printf("%s\n", windowTitle);
|
||||
printf("%s", prompt);
|
||||
|
||||
if (numChoices > 10) {
|
||||
numChoices = 10;
|
||||
}
|
||||
|
||||
int c = -1;
|
||||
if (numChoices > 1) {
|
||||
printf("\n");
|
||||
printf("Choose an option by number:");
|
||||
|
||||
while ((c < 0) || (c >= numChoices)) {
|
||||
printf("\n");
|
||||
|
||||
for (int i = 0; i < numChoices; i++) {
|
||||
if (numChoices <= 3) {
|
||||
printf(" (%d) %s ", i, choice[i]);
|
||||
} else {
|
||||
printf(" (%d) %s\n", i, choice[i]);
|
||||
}
|
||||
}
|
||||
|
||||
printf("\n> ");
|
||||
c = _getch() - '0';
|
||||
|
||||
if ((c < 0) || (c >= numChoices)) {
|
||||
printf("'%d' is not a valid choice.", c);
|
||||
} else {
|
||||
printf("%d", c);
|
||||
}
|
||||
}
|
||||
|
||||
} else if (numChoices == 1) {
|
||||
|
||||
printf("\nPress any key for '%s'...", choice[0]);
|
||||
_getch();
|
||||
c = 0;
|
||||
|
||||
} else {
|
||||
|
||||
printf("\nPress any key...");
|
||||
_getch();
|
||||
c = 0;
|
||||
}
|
||||
|
||||
printf("\n___________________________________________________\n");
|
||||
return c;
|
||||
}
|
||||
|
||||
#ifdef G3D_OSX
|
||||
|
||||
// See http://developer.apple.com/documentation/Carbon/Reference/Carbon_Event_Manager_Ref/index.html
|
||||
|
||||
#define CARBON_COMMANDID_START 128
|
||||
#define CARBON_BUTTON_SPACING 12
|
||||
#define CARBON_BUTTON_HEIGHT 20
|
||||
#define CARBON_BUTTON_MINWIDTH 69
|
||||
#define CARBON_WINDOW_PADDING 20
|
||||
|
||||
struct CallbackData {
|
||||
WindowRef refWindow;
|
||||
|
||||
/** Index of this particular button */
|
||||
int myIndex;
|
||||
|
||||
/** Buttons store their index into here when pressed. */
|
||||
int* whichButton;
|
||||
};
|
||||
|
||||
/**
|
||||
Assumes that userData is a pointer to a carbon_evt_data_t.
|
||||
|
||||
*/
|
||||
static pascal OSStatus DoCommandEvent(EventHandlerCallRef handlerRef, EventRef event, void* userData) {
|
||||
// See http://developer.apple.com/documentation/Carbon/Conceptual/HandlingWindowsControls/index.html
|
||||
|
||||
CallbackData& callbackData = *(CallbackData*)userData;
|
||||
|
||||
# pragma unused(handlerRef)
|
||||
|
||||
callbackData.whichButton[0] = callbackData.myIndex;
|
||||
|
||||
// If we get here we can close the window
|
||||
::QuitAppModalLoopForWindow(callbackData.refWindow);
|
||||
|
||||
// Return noErr to indicate that we handled the event
|
||||
return noErr;
|
||||
}
|
||||
|
||||
static int guiPrompt
|
||||
(const char* windowTitle,
|
||||
const char* prompt,
|
||||
const char** choice,
|
||||
int numChoices) {
|
||||
|
||||
WindowRef window;
|
||||
|
||||
int iNumButtonRows = 0;
|
||||
int iButtonWidth = -1;
|
||||
OSStatus err = noErr;
|
||||
|
||||
// Determine number of rows of buttons
|
||||
while (iButtonWidth < CARBON_BUTTON_MINWIDTH) {
|
||||
++iNumButtonRows;
|
||||
iButtonWidth =
|
||||
(550 - (CARBON_WINDOW_PADDING*2 +
|
||||
(CARBON_BUTTON_SPACING*numChoices))) /
|
||||
(numChoices/iNumButtonRows);
|
||||
}
|
||||
|
||||
// Window Variables
|
||||
Rect rectWin = {0, 0, 200 + ((iNumButtonRows-1) * (CARBON_BUTTON_HEIGHT+CARBON_BUTTON_SPACING)), 550}; // top, left, bottom, right
|
||||
CFStringRef szWindowTitle = CFStringCreateWithCString(kCFAllocatorDefault, windowTitle, kCFStringEncodingUTF8);
|
||||
|
||||
window = NULL;
|
||||
|
||||
err = CreateNewWindow(kMovableAlertWindowClass, kWindowStandardHandlerAttribute|kWindowCompositingAttribute, &rectWin, &window);
|
||||
err = SetWindowTitleWithCFString(window, szWindowTitle);
|
||||
err = SetThemeWindowBackground(window, kThemeBrushAlertBackgroundActive, false);
|
||||
assert(err == noErr);
|
||||
|
||||
// Event Handler Variables
|
||||
EventTypeSpec buttonSpec[] = {{ kEventClassControl, kEventControlHit }, { kEventClassCommand, kEventCommandProcess }};
|
||||
EventHandlerUPP buttonHandler = NewEventHandlerUPP(DoCommandEvent);
|
||||
|
||||
// Static Text Variables
|
||||
Rect rectStatic = {20, 20, 152, 530};
|
||||
CFStringRef szStaticText = CFStringCreateWithCString(kCFAllocatorDefault, prompt, kCFStringEncodingUTF8);
|
||||
ControlRef refStaticText = NULL;
|
||||
err = CreateStaticTextControl(window, &rectStatic, szStaticText, NULL, &refStaticText);
|
||||
|
||||
// Button Variables
|
||||
Rect bounds[numChoices];
|
||||
CFStringRef caption[numChoices];
|
||||
ControlRef button[numChoices];
|
||||
|
||||
int whichButton=-1;
|
||||
CallbackData callbackData[numChoices];
|
||||
|
||||
// Create the Buttons and assign event handlers
|
||||
for (int i = 0; i < numChoices; ++i) {
|
||||
bounds[i].top = 160 + ((CARBON_BUTTON_HEIGHT+CARBON_BUTTON_SPACING)*(i%iNumButtonRows));
|
||||
bounds[i].right = 530 - ((iButtonWidth+CARBON_BUTTON_SPACING)*(i/iNumButtonRows));
|
||||
bounds[i].left = bounds[i].right - iButtonWidth;
|
||||
bounds[i].bottom = bounds[i].top + CARBON_BUTTON_HEIGHT;
|
||||
|
||||
// Convert the button captions to Apple strings
|
||||
caption[i] = CFStringCreateWithCString(kCFAllocatorDefault, choice[i], kCFStringEncodingUTF8);
|
||||
|
||||
err = CreatePushButtonControl(window, &bounds[i], caption[i], &button[i]);
|
||||
assert(err == noErr);
|
||||
|
||||
err = SetControlCommandID(button[i], CARBON_COMMANDID_START + i);
|
||||
assert(err == noErr);
|
||||
|
||||
callbackData[i].refWindow = window;
|
||||
callbackData[i].myIndex = i;
|
||||
callbackData[i].whichButton = &whichButton;
|
||||
|
||||
err = InstallControlEventHandler(button[i], buttonHandler,
|
||||
GetEventTypeCount(buttonSpec), buttonSpec,
|
||||
&callbackData[i], NULL);
|
||||
assert(err == noErr);
|
||||
}
|
||||
|
||||
// Show Dialog
|
||||
err = RepositionWindow(window, NULL, kWindowCenterOnMainScreen);
|
||||
ShowWindow(window);
|
||||
BringToFront(window);
|
||||
err = ActivateWindow(window, true);
|
||||
|
||||
// Hack to get our window/process to the front...
|
||||
ProcessSerialNumber psn = { 0, kCurrentProcess};
|
||||
TransformProcessType(&psn, kProcessTransformToForegroundApplication);
|
||||
SetFrontProcess (&psn);
|
||||
|
||||
// Run in Modal State
|
||||
err = RunAppModalLoopForWindow(window);
|
||||
|
||||
// Dispose of Button Related Data
|
||||
for (int i = 0; i < numChoices; ++i) {
|
||||
// Dispose of controls
|
||||
DisposeControl(button[i]);
|
||||
|
||||
// Release CFStrings
|
||||
CFRelease(caption[i]);
|
||||
}
|
||||
|
||||
// Dispose of Other Controls
|
||||
DisposeControl(refStaticText);
|
||||
|
||||
// Dispose of Event Handlers
|
||||
DisposeEventHandlerUPP(buttonHandler);
|
||||
|
||||
// Dispose of Window
|
||||
DisposeWindow(window);
|
||||
|
||||
// Release CFStrings
|
||||
CFRelease(szWindowTitle);
|
||||
CFRelease(szStaticText);
|
||||
|
||||
// Return Selection
|
||||
return whichButton;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
int prompt(
|
||||
const char* windowTitle,
|
||||
const char* prompt,
|
||||
const char** choice,
|
||||
int numChoices,
|
||||
bool useGui) {
|
||||
|
||||
#ifdef G3D_WIN32
|
||||
if (useGui) {
|
||||
// Build the message box
|
||||
return guiPrompt(windowTitle, prompt, choice, numChoices);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef G3D_OSX
|
||||
if (useGui){
|
||||
//Will default to text prompt if numChoices > 4
|
||||
return guiPrompt(windowTitle, prompt, choice, numChoices);
|
||||
}
|
||||
#endif
|
||||
return textPrompt(windowTitle, prompt, choice, numChoices);
|
||||
}
|
||||
|
||||
|
||||
void msgBox(
|
||||
const std::string& message,
|
||||
const std::string& title) {
|
||||
|
||||
const char *choice[] = {"Ok"};
|
||||
prompt(title.c_str(), message.c_str(), choice, 1, true);
|
||||
}
|
||||
|
||||
#ifndef G3D_WIN32
|
||||
#undef _getch
|
||||
#endif
|
||||
|
||||
};// namespace
|
||||
|
||||
275
externals/g3dlite/stringutils.cpp
vendored
Normal file
275
externals/g3dlite/stringutils.cpp
vendored
Normal file
@@ -0,0 +1,275 @@
|
||||
/**
|
||||
@file stringutils.cpp
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
@created 2000-09-09
|
||||
@edited 2008-01-10
|
||||
*/
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/stringutils.h"
|
||||
#include "G3D/BinaryInput.h"
|
||||
#include <algorithm>
|
||||
|
||||
namespace G3D {
|
||||
|
||||
#ifdef _MSC_VER
|
||||
// disable: "C++ exception handler used"
|
||||
# pragma warning (push)
|
||||
# pragma warning (disable : 4530)
|
||||
#endif
|
||||
#ifdef G3D_WIN32
|
||||
const char* NEWLINE = "\r\n";
|
||||
#else
|
||||
const char* NEWLINE = "\n";
|
||||
static bool iswspace(int ch) { return (ch==' ' || ch=='\t' || ch=='\n' || ch=='\r'); }
|
||||
#endif
|
||||
|
||||
void parseCommaSeparated(const std::string s, Array<std::string>& array, bool stripQuotes) {
|
||||
array.fastClear();
|
||||
if (s == "") {
|
||||
return;
|
||||
}
|
||||
|
||||
size_t begin = 0;
|
||||
const char delimiter = ',';
|
||||
const char quote = '\"';
|
||||
do {
|
||||
size_t end = begin;
|
||||
// Find the next comma, or the end of the string
|
||||
bool inQuotes = false;
|
||||
while ((end < s.length()) && (inQuotes || (s[end] != delimiter))) {
|
||||
if (s[end] == quote) {
|
||||
if ((end < s.length() - 2) && (s[end + 1] == quote) && (s[end + 2]) == quote) {
|
||||
// Skip over the superquote
|
||||
end += 2;
|
||||
}
|
||||
inQuotes = ! inQuotes;
|
||||
}
|
||||
++end;
|
||||
}
|
||||
array.append(s.substr(begin, end - begin));
|
||||
begin = end + 1;
|
||||
} while (begin < s.length());
|
||||
|
||||
if (stripQuotes) {
|
||||
for (int i = 0; i < array.length(); ++i) {
|
||||
std::string& t = array[i];
|
||||
int L = t.length();
|
||||
if ((L > 1) && (t[0] == quote) && (t[L - 1] == quote)) {
|
||||
if ((L > 6) && (t[1] == quote) && (t[2] == quote) && (t[L - 3] == quote) && (t[L - 2] == quote)) {
|
||||
// Triple-quote
|
||||
t = t.substr(3, L - 6);
|
||||
} else {
|
||||
// Double-quote
|
||||
t = t.substr(1, L - 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool beginsWith(
|
||||
const std::string& test,
|
||||
const std::string& pattern) {
|
||||
|
||||
if (test.size() >= pattern.size()) {
|
||||
for (int i = 0; i < (int)pattern.size(); ++i) {
|
||||
if (pattern[i] != test[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool endsWith(
|
||||
const std::string& test,
|
||||
const std::string& pattern) {
|
||||
|
||||
if (test.size() >= pattern.size()) {
|
||||
int te = test.size() - 1;
|
||||
int pe = pattern.size() - 1;
|
||||
for (int i = pattern.size() - 1; i >= 0; --i) {
|
||||
if (pattern[pe - i] != test[te - i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::string wordWrap(
|
||||
const std::string& input,
|
||||
int numCols) {
|
||||
|
||||
std::string output;
|
||||
size_t c = 0;
|
||||
int len;
|
||||
|
||||
// Don't make lines less than this length
|
||||
int minLength = numCols / 4;
|
||||
size_t inLen = input.size();
|
||||
|
||||
bool first = true;
|
||||
while (c < inLen) {
|
||||
if (first) {
|
||||
first = false;
|
||||
} else {
|
||||
output += NEWLINE;
|
||||
}
|
||||
|
||||
if ((int)inLen - (int)c - 1 < numCols) {
|
||||
// The end
|
||||
output += input.substr(c, inLen - c);
|
||||
break;
|
||||
}
|
||||
|
||||
len = numCols;
|
||||
|
||||
// Look at character c + numCols, see if it is a space.
|
||||
while ((len > minLength) &&
|
||||
(input[c + len] != ' ')) {
|
||||
len--;
|
||||
}
|
||||
|
||||
if (len == minLength) {
|
||||
// Just crop
|
||||
len = numCols;
|
||||
|
||||
}
|
||||
|
||||
output += input.substr(c, len);
|
||||
c += len;
|
||||
if (c < input.size()) {
|
||||
// Collapse multiple spaces.
|
||||
while ((input[c] == ' ') && (c < input.size())) {
|
||||
c++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
int stringCompare(
|
||||
const std::string& s1,
|
||||
const std::string& s2) {
|
||||
|
||||
return stringPtrCompare(&s1, &s2);
|
||||
}
|
||||
|
||||
|
||||
int stringPtrCompare(
|
||||
const std::string* s1,
|
||||
const std::string* s2) {
|
||||
|
||||
return s1->compare(*s2);
|
||||
}
|
||||
|
||||
|
||||
std::string toUpper(const std::string& x) {
|
||||
std::string result = x;
|
||||
std::transform(result.begin(), result.end(), result.begin(), toupper);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
std::string toLower(const std::string& x) {
|
||||
std::string result = x;
|
||||
std::transform(result.begin(), result.end(), result.begin(), tolower);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
Array<std::string> stringSplit(
|
||||
const std::string& x,
|
||||
char splitChar) {
|
||||
|
||||
Array<std::string> out;
|
||||
|
||||
// Pointers to the beginning and end of the substring
|
||||
const char* start = x.c_str();
|
||||
const char* stop = start;
|
||||
|
||||
while ((stop = strchr(start, splitChar))) {
|
||||
out.append(std::string(start, stop - start));
|
||||
start = stop + 1;
|
||||
}
|
||||
|
||||
// Append the last one
|
||||
out.append(std::string(start));
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
std::string stringJoin(
|
||||
const Array<std::string>& a,
|
||||
char joinChar) {
|
||||
|
||||
std::string out;
|
||||
|
||||
for (int i = 0; i < (int)a.size() - 1; ++i) {
|
||||
out += a[i] + joinChar;
|
||||
}
|
||||
|
||||
if (a.size() > 0) {
|
||||
return out + a.last();
|
||||
} else {
|
||||
return out;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::string stringJoin(
|
||||
const Array<std::string>& a,
|
||||
const std::string& joinStr) {
|
||||
|
||||
std::string out;
|
||||
|
||||
for (int i = 0; i < (int)a.size() - 1; ++i) {
|
||||
out += a[i] + joinStr;
|
||||
}
|
||||
|
||||
if (a.size() > 0) {
|
||||
return out + a.last();
|
||||
} else {
|
||||
return out;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::string trimWhitespace(
|
||||
const std::string& s) {
|
||||
|
||||
size_t left = 0;
|
||||
|
||||
// Trim from left
|
||||
while ((left < s.length()) && iswspace(s[left])) {
|
||||
++left;
|
||||
}
|
||||
|
||||
int right = s.length() - 1;
|
||||
// Trim from right
|
||||
while ((right > (int)left) && iswspace(s[right])) {
|
||||
--right;
|
||||
}
|
||||
|
||||
return s.substr(left, right - left + 1);
|
||||
}
|
||||
|
||||
}; // namespace
|
||||
|
||||
#undef NEWLINE
|
||||
#ifdef _MSC_VER
|
||||
# pragma warning (pop)
|
||||
#endif
|
||||
32
externals/jemalloc/CMakeLists.txt
vendored
32
externals/jemalloc/CMakeLists.txt
vendored
@@ -1,27 +1,15 @@
|
||||
SET(jmalloc_STAT_SRC
|
||||
arena.c
|
||||
chunk.c
|
||||
chunk_mmap.c
|
||||
ckh.c
|
||||
extent.c
|
||||
huge.c
|
||||
mb.c
|
||||
prof.c
|
||||
tcache.c
|
||||
base.c
|
||||
chunk_dss.c
|
||||
chunk_swap.c
|
||||
ctl.c
|
||||
hash.c
|
||||
jemalloc.c
|
||||
mutex.c
|
||||
stats.c
|
||||
)
|
||||
|
||||
file(GLOB sources *.c)
|
||||
set(jemalloc_STAT_SRC
|
||||
${sources}
|
||||
)
|
||||
|
||||
include_directories(
|
||||
${CMAKE_SOURCE_DIR}/dep/include
|
||||
)
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/internal
|
||||
)
|
||||
|
||||
add_definitions(-D_GNU_SOURCE -D_REENTRANT)
|
||||
|
||||
add_library(jmalloc STATIC ${jmalloc_STAT_SRC})
|
||||
add_library(jemalloc STATIC ${sources})
|
||||
|
||||
0
externals/mersennetwister/delme
vendored
0
externals/mersennetwister/delme
vendored
24
externals/sockets/CMakeLists.txt
vendored
24
externals/sockets/CMakeLists.txt
vendored
@@ -1,26 +1,10 @@
|
||||
SET(trinitysockets_STAT_SRCS
|
||||
Base64.cpp
|
||||
Exception.cpp
|
||||
Ipv4Address.cpp
|
||||
Ipv6Address.cpp
|
||||
Lock.cpp
|
||||
Mutex.cpp
|
||||
Parse.cpp
|
||||
ResolvServer.cpp
|
||||
ResolvSocket.cpp
|
||||
Socket.cpp
|
||||
SocketHandler.cpp
|
||||
StdoutLog.cpp
|
||||
StreamSocket.cpp
|
||||
TcpSocket.cpp
|
||||
Thread.cpp
|
||||
UdpSocket.cpp
|
||||
Utility.cpp
|
||||
socket_include.cpp
|
||||
file(GLOB sources *.cpp)
|
||||
set(trinitysockets_STAT_SRCS
|
||||
${sources}
|
||||
)
|
||||
|
||||
include_directories(
|
||||
${CMAKE_SOURCE_DIR}/dep/include/sockets
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include
|
||||
)
|
||||
|
||||
add_library(trinitysockets STATIC ${trinitysockets_STAT_SRCS})
|
||||
|
||||
136
externals/sockets/Makefile
vendored
Normal file
136
externals/sockets/Makefile
vendored
Normal file
@@ -0,0 +1,136 @@
|
||||
# CMAKE generated file: DO NOT EDIT!
|
||||
# Generated by "Unix Makefiles" Generator, CMake Version 2.6
|
||||
|
||||
# Default target executed when no arguments are given to make.
|
||||
default_target: all
|
||||
.PHONY : default_target
|
||||
|
||||
#=============================================================================
|
||||
# Special targets provided by cmake.
|
||||
|
||||
# Disable implicit rules so canoncical targets will work.
|
||||
.SUFFIXES:
|
||||
|
||||
# Remove some rules from gmake that .SUFFIXES does not remove.
|
||||
SUFFIXES =
|
||||
|
||||
.SUFFIXES: .hpux_make_needs_suffix_list
|
||||
|
||||
# Suppress display of executed commands.
|
||||
$(VERBOSE).SILENT:
|
||||
|
||||
# A target that is always out of date.
|
||||
cmake_force:
|
||||
.PHONY : cmake_force
|
||||
|
||||
#=============================================================================
|
||||
# Set environment variables for the build.
|
||||
|
||||
# The shell in which to execute make rules.
|
||||
SHELL = /bin/sh
|
||||
|
||||
# The CMake executable.
|
||||
CMAKE_COMMAND = /usr/bin/cmake
|
||||
|
||||
# The command to remove a file.
|
||||
RM = /usr/bin/cmake -E remove -f
|
||||
|
||||
# The program to use to edit the cache.
|
||||
CMAKE_EDIT_COMMAND = /usr/bin/ccmake
|
||||
|
||||
# The top-level source directory on which CMake was run.
|
||||
CMAKE_SOURCE_DIR = /home/trinity/dev/trinitycore/externals/sockets
|
||||
|
||||
# The top-level build directory on which CMake was run.
|
||||
CMAKE_BINARY_DIR = /home/trinity/dev/trinitycore/externals/sockets
|
||||
|
||||
#=============================================================================
|
||||
# Targets provided globally by CMake.
|
||||
|
||||
# Special rule for the target edit_cache
|
||||
edit_cache:
|
||||
@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake cache editor..."
|
||||
/usr/bin/ccmake -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR)
|
||||
.PHONY : edit_cache
|
||||
|
||||
# Special rule for the target edit_cache
|
||||
edit_cache/fast: edit_cache
|
||||
.PHONY : edit_cache/fast
|
||||
|
||||
# Special rule for the target rebuild_cache
|
||||
rebuild_cache:
|
||||
@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake to regenerate build system..."
|
||||
/usr/bin/cmake -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR)
|
||||
.PHONY : rebuild_cache
|
||||
|
||||
# Special rule for the target rebuild_cache
|
||||
rebuild_cache/fast: rebuild_cache
|
||||
.PHONY : rebuild_cache/fast
|
||||
|
||||
# The main all target
|
||||
all: cmake_check_build_system
|
||||
$(CMAKE_COMMAND) -E cmake_progress_start /home/trinity/dev/trinitycore/externals/sockets/CMakeFiles /home/trinity/dev/trinitycore/externals/sockets/CMakeFiles/progress.make
|
||||
$(MAKE) -f CMakeFiles/Makefile2 all
|
||||
$(CMAKE_COMMAND) -E cmake_progress_start /home/trinity/dev/trinitycore/externals/sockets/CMakeFiles 0
|
||||
.PHONY : all
|
||||
|
||||
# The main clean target
|
||||
clean:
|
||||
$(MAKE) -f CMakeFiles/Makefile2 clean
|
||||
.PHONY : clean
|
||||
|
||||
# The main clean target
|
||||
clean/fast: clean
|
||||
.PHONY : clean/fast
|
||||
|
||||
# Prepare targets for installation.
|
||||
preinstall: all
|
||||
$(MAKE) -f CMakeFiles/Makefile2 preinstall
|
||||
.PHONY : preinstall
|
||||
|
||||
# Prepare targets for installation.
|
||||
preinstall/fast:
|
||||
$(MAKE) -f CMakeFiles/Makefile2 preinstall
|
||||
.PHONY : preinstall/fast
|
||||
|
||||
# clear depends
|
||||
depend:
|
||||
$(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 1
|
||||
.PHONY : depend
|
||||
|
||||
#=============================================================================
|
||||
# Target rules for targets named trinitysockets
|
||||
|
||||
# Build rule for target.
|
||||
trinitysockets: cmake_check_build_system
|
||||
$(MAKE) -f CMakeFiles/Makefile2 trinitysockets
|
||||
.PHONY : trinitysockets
|
||||
|
||||
# fast build rule for target.
|
||||
trinitysockets/fast:
|
||||
$(MAKE) -f CMakeFiles/trinitysockets.dir/build.make CMakeFiles/trinitysockets.dir/build
|
||||
.PHONY : trinitysockets/fast
|
||||
|
||||
# Help Target
|
||||
help:
|
||||
@echo "The following are some of the valid targets for this Makefile:"
|
||||
@echo "... all (the default if no target is provided)"
|
||||
@echo "... clean"
|
||||
@echo "... depend"
|
||||
@echo "... edit_cache"
|
||||
@echo "... rebuild_cache"
|
||||
@echo "... trinitysockets"
|
||||
.PHONY : help
|
||||
|
||||
|
||||
|
||||
#=============================================================================
|
||||
# Special targets to cleanup operation of make.
|
||||
|
||||
# Special rule to run CMake to check the build system integrity.
|
||||
# No rule that depends on this can have commands that come from listfiles
|
||||
# because they might be regenerated.
|
||||
cmake_check_build_system:
|
||||
$(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 0
|
||||
.PHONY : cmake_check_build_system
|
||||
|
||||
12
externals/zlib/CMakeLists.txt
vendored
Normal file
12
externals/zlib/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
file(GLOB sources *.c)
|
||||
file(GLOB headers *.h)
|
||||
|
||||
SET(zlib_STAT_SRCS
|
||||
${sources}
|
||||
)
|
||||
|
||||
include_directories(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
)
|
||||
|
||||
add_library(zlib STATIC ${zlib_STAT_SRCS})
|
||||
1208
externals/zlib/ChangeLog
vendored
1208
externals/zlib/ChangeLog
vendored
File diff suppressed because it is too large
Load Diff
115
externals/zlib/README
vendored
115
externals/zlib/README
vendored
@@ -1,115 +0,0 @@
|
||||
ZLIB DATA COMPRESSION LIBRARY
|
||||
|
||||
zlib 1.2.5 is a general purpose data compression library. All the code is
|
||||
thread safe. The data format used by the zlib library is described by RFCs
|
||||
(Request for Comments) 1950 to 1952 in the files
|
||||
http://www.ietf.org/rfc/rfc1950.txt (zlib format), rfc1951.txt (deflate format)
|
||||
and rfc1952.txt (gzip format).
|
||||
|
||||
All functions of the compression library are documented in the file zlib.h
|
||||
(volunteer to write man pages welcome, contact zlib@gzip.org). A usage example
|
||||
of the library is given in the file example.c which also tests that the library
|
||||
is working correctly. Another example is given in the file minigzip.c. The
|
||||
compression library itself is composed of all source files except example.c and
|
||||
minigzip.c.
|
||||
|
||||
To compile all files and run the test program, follow the instructions given at
|
||||
the top of Makefile.in. In short "./configure; make test", and if that goes
|
||||
well, "make install" should work for most flavors of Unix. For Windows, use one
|
||||
of the special makefiles in win32/ or contrib/vstudio/ . For VMS, use
|
||||
make_vms.com.
|
||||
|
||||
Questions about zlib should be sent to <zlib@gzip.org>, or to Gilles Vollant
|
||||
<info@winimage.com> for the Windows DLL version. The zlib home page is
|
||||
http://zlib.net/ . Before reporting a problem, please check this site to
|
||||
verify that you have the latest version of zlib; otherwise get the latest
|
||||
version and check whether the problem still exists or not.
|
||||
|
||||
PLEASE read the zlib FAQ http://zlib.net/zlib_faq.html before asking for help.
|
||||
|
||||
Mark Nelson <markn@ieee.org> wrote an article about zlib for the Jan. 1997
|
||||
issue of Dr. Dobb's Journal; a copy of the article is available at
|
||||
http://marknelson.us/1997/01/01/zlib-engine/ .
|
||||
|
||||
The changes made in version 1.2.5 are documented in the file ChangeLog.
|
||||
|
||||
Unsupported third party contributions are provided in directory contrib/ .
|
||||
|
||||
zlib is available in Java using the java.util.zip package, documented at
|
||||
http://java.sun.com/developer/technicalArticles/Programming/compression/ .
|
||||
|
||||
A Perl interface to zlib written by Paul Marquess <pmqs@cpan.org> is available
|
||||
at CPAN (Comprehensive Perl Archive Network) sites, including
|
||||
http://search.cpan.org/~pmqs/IO-Compress-Zlib/ .
|
||||
|
||||
A Python interface to zlib written by A.M. Kuchling <amk@amk.ca> is
|
||||
available in Python 1.5 and later versions, see
|
||||
http://www.python.org/doc/lib/module-zlib.html .
|
||||
|
||||
zlib is built into tcl: http://wiki.tcl.tk/4610 .
|
||||
|
||||
An experimental package to read and write files in .zip format, written on top
|
||||
of zlib by Gilles Vollant <info@winimage.com>, is available in the
|
||||
contrib/minizip directory of zlib.
|
||||
|
||||
|
||||
Notes for some targets:
|
||||
|
||||
- For Windows DLL versions, please see win32/DLL_FAQ.txt
|
||||
|
||||
- For 64-bit Irix, deflate.c must be compiled without any optimization. With
|
||||
-O, one libpng test fails. The test works in 32 bit mode (with the -n32
|
||||
compiler flag). The compiler bug has been reported to SGI.
|
||||
|
||||
- zlib doesn't work with gcc 2.6.3 on a DEC 3000/300LX under OSF/1 2.1 it works
|
||||
when compiled with cc.
|
||||
|
||||
- On Digital Unix 4.0D (formely OSF/1) on AlphaServer, the cc option -std1 is
|
||||
necessary to get gzprintf working correctly. This is done by configure.
|
||||
|
||||
- zlib doesn't work on HP-UX 9.05 with some versions of /bin/cc. It works with
|
||||
other compilers. Use "make test" to check your compiler.
|
||||
|
||||
- gzdopen is not supported on RISCOS or BEOS.
|
||||
|
||||
- For PalmOs, see http://palmzlib.sourceforge.net/
|
||||
|
||||
|
||||
Acknowledgments:
|
||||
|
||||
The deflate format used by zlib was defined by Phil Katz. The deflate and
|
||||
zlib specifications were written by L. Peter Deutsch. Thanks to all the
|
||||
people who reported problems and suggested various improvements in zlib; they
|
||||
are too numerous to cite here.
|
||||
|
||||
Copyright notice:
|
||||
|
||||
(C) 1995-2010 Jean-loup Gailly and Mark Adler
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
Jean-loup Gailly Mark Adler
|
||||
jloup@gzip.org madler@alumni.caltech.edu
|
||||
|
||||
If you use the zlib library in a product, we would appreciate *not* receiving
|
||||
lengthy legal documents to sign. The sources are provided for free but without
|
||||
warranty of any kind. The library has been entirely written by Jean-loup
|
||||
Gailly and Mark Adler; it does not include third-party code.
|
||||
|
||||
If you redistribute modified sources, we would appreciate that you include in
|
||||
the file ChangeLog history information documenting your changes. Please read
|
||||
the FAQ for more information on the distribution of modified source versions.
|
||||
@@ -4,21 +4,21 @@
|
||||
SET(collision_STAT_SRCS
|
||||
BoundingIntervalHierarchy.h
|
||||
BoundingIntervalHierarchy.cpp
|
||||
Management/IVMapManager.h
|
||||
Maps/MapTree.cpp
|
||||
Maps/MapTree.h
|
||||
Models/ModelInstance.cpp
|
||||
Models/ModelInstance.h
|
||||
Maps/TileAssembler.cpp
|
||||
Maps/TileAssembler.h
|
||||
VMapDefinitions.h
|
||||
Models/ModelInstance.cpp
|
||||
Models/ModelInstance.h
|
||||
Models/WorldModel.cpp
|
||||
Models/WorldModel.h
|
||||
Management/IVMapManager.h
|
||||
Management/VMapFactory.cpp
|
||||
Management/VMapFactory.h
|
||||
Management/VMapManager2.cpp
|
||||
Management/VMapManager2.h
|
||||
VMapDefinitions.h
|
||||
VMapTools.h
|
||||
Models/WorldModel.cpp
|
||||
Models/WorldModel.h
|
||||
)
|
||||
|
||||
include_directories(
|
||||
|
||||
@@ -404,6 +404,8 @@ include_directories(
|
||||
|
||||
if(NOT DO_SCRIPTS)
|
||||
SET(game_STAT_SRCS ${game_STAT_SRCS}
|
||||
PrecompiledHeaders/ScriptPCH.cpp
|
||||
PrecompiledHeaders/ScriptPCH.h
|
||||
AI/ScriptedAI/ScriptedEscortAI.cpp
|
||||
AI/ScriptedAI/ScriptedEscortAI.h
|
||||
AI/ScriptedAI/ScriptedCreature.cpp
|
||||
@@ -416,8 +418,6 @@ if(NOT DO_SCRIPTS)
|
||||
AI/ScriptedAI/ScriptedInstance.h
|
||||
AI/ScriptedAI/ScriptedSimpleAI.cpp
|
||||
AI/ScriptedAI/ScriptedSimpleAI.h
|
||||
PrecompiledHeaders/ScriptPCH.cpp
|
||||
PrecompiledHeaders/ScriptPCH.h
|
||||
)
|
||||
message("-- Added Script Engine to GAME lib")
|
||||
endif(NOT DO_SCRIPTS)
|
||||
|
||||
@@ -133,10 +133,14 @@ target_link_libraries(
|
||||
trinity-core
|
||||
game
|
||||
shared
|
||||
zlib
|
||||
trinitysockets
|
||||
trinitydatabase
|
||||
trinityauth
|
||||
trinityconfig
|
||||
collision
|
||||
g3dlib
|
||||
jemalloc
|
||||
${SCRIPT_LIB}
|
||||
${READLINE_LIBRARY}
|
||||
${TERMCAP_LIBRARY}
|
||||
|
||||
Reference in New Issue
Block a user