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:
1 parent
c08a7d6348
commit
f867f6d7a8
93 files changed
+19175
-1812
No files matched your search
+81
-77
@@ -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)
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Vendored
+7
@@ -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)
|
||||
Vendored
+14
-1
@@ -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
|
||||
Vendored
-319
@@ -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.
|
||||
|
||||
Vendored
+10
@@ -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})
|
||||
Vendored
-42
@@ -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
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
Vendored
+366
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
Vendored
+1237
File diff suppressed because it is too large.
Load diff
Vendored
+81
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
Vendored
+568
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
Vendored
+522
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
Vendored
+393
@@ -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
|
||||
Vendored
+11
@@ -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})
|
||||
Vendored
+179
@@ -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
File diff suppressed because it is too large.
Load diff
+436
@@ -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
|
||||
Vendored
+70
@@ -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
|
||||
Vendored
+176
@@ -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
|
||||
Vendored
+89
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Vendored
+236
@@ -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;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Vendored
+146
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
Vendored
+1927
File diff suppressed because it is too large.
Load diff
Vendored
+523
@@ -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
|
||||
|
||||
|
||||
Vendored
+91
@@ -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;
|
||||
}
|
||||
}
|
||||
Vendored
+149
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
Vendored
+583
@@ -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); }
|
||||
}
|
||||
|
||||
Vendored
+212
@@ -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
|
||||
Vendored
+218
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Vendored
+61
@@ -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
|
||||
Vendored
+223
@@ -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
|
||||
Vendored
+1746
File diff suppressed because it is too large.
Load diff
Vendored
+1136
File diff suppressed because it is too large.
Load diff
Vendored
+452
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
Vendored
+186
@@ -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
|
||||
Vendored
+132
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Vendored
+224
@@ -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
|
||||
Vendored
+507
@@ -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
|
||||
Vendored
+520
@@ -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
|
||||
Vendored
+389
@@ -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
|
||||
Vendored
+1165
File diff suppressed because it is too large.
Load diff
Vendored
+164
@@ -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
|
||||
Vendored
+204
@@ -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
|
||||
|
||||
Vendored
+108
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
Vendored
+729
@@ -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
|
||||
|
||||
Vendored
+275
@@ -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
|
||||
Vendored
+10
-22
@@ -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})
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
Vendored
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Vendored
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Vendored
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Vendored
File renamed without changes.
Vendored
Whitespace-only changes.
Vendored
+4
-20
@@ -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})
|
||||
Vendored
+136
@@ -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
|
||||
|
||||
Vendored
+12
@@ -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})
|
||||
Vendored
-1208
File diff suppressed because it is too large.
Load diff
Vendored
-115
@@ -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