Merge internal repository.

Delete TODO list, use issue list instead.
2.0
castano 17 years ago
parent a7ac577d15
commit 645eda8fd4

@ -1,20 +0,0 @@
Short term:
- Improve quality of fast compressors.
- More accelerated compressors.
- Accelerate mipmap generation.
- Generic RGB pixel format conversion.
- Do not assume that alpha is used for transparency.
Longer term:
- support for DXT1a format.
- support for correct cubemap filtering.
- support for correct cubemap borders and atlas borders. (Crytek request)
- support for 3d textures & 3d compression.
- Add support for occlusion map, horizon map & bent normal map generation.
- Add support for accurate normal map mipmap computation. Using lighting integrals.
- Add support for YCoCg and JPEG-LS color transforms. Add high quality DXT5-RGB compression.
- Add full support for mirror wrap mode.
- Generation of cone maps for relief mapping.
- Add min/max box mipmap filters.

@ -53,7 +53,6 @@ FIND_LIBRARY (CUDA_RUNTIME_LIBRARY
${CUDA_COMPILER_DIR}
DOC "The CUDA runtime library")
IF (CUDA_INCLUDE_PATH AND CUDA_LIBRARY AND CUDA_RUNTIME_LIBRARY)
SET (CUDA_FOUND 1 CACHE STRING "Set to 1 if CUDA is found, 0 otherwise")
ELSE (CUDA_INCLUDE_PATH AND CUDA_LIBRARY AND CUDA_RUNTIME_LIBRARY)

@ -1,129 +1,129 @@
#
# Try to find nVidia's Cg compiler, runtime libraries, and include path.
# Once done this will define
#
# CG_FOUND =system has NVidia Cg and it can be used.
# CG_INCLUDE_PATH = directory where cg.h resides
# CG_LIBRARY = full path to libCg.so (Cg.DLL on win32)
# CG_GL_LIBRARY = full path to libCgGL.so (CgGL.dll on win32)
# CG_COMPILER = full path to cgc (cgc.exe on win32)
#
# On OSX default to using the framework version of Cg.
IF (APPLE)
INCLUDE(${CMAKE_ROOT}/Modules/CMakeFindFrameworks.cmake)
SET(CG_FRAMEWORK_INCLUDES)
CMAKE_FIND_FRAMEWORKS(Cg)
IF (Cg_FRAMEWORKS)
FOREACH(dir ${Cg_FRAMEWORKS})
SET(CG_FRAMEWORK_INCLUDES ${CG_FRAMEWORK_INCLUDES}
${dir}/Headers ${dir}/PrivateHeaders)
ENDFOREACH(dir)
# Find the include dir
FIND_PATH(CG_INCLUDE_PATH cg.h
${CG_FRAMEWORK_INCLUDES}
)
# Since we are using Cg framework, we must link to it.
# Note, we use weak linking, so that it works even when Cg is not available.
SET(CG_LIBRARY "-weak_framework Cg" CACHE STRING "Cg library")
SET(CG_GL_LIBRARY "-weak_framework Cg" CACHE STRING "Cg GL library")
ENDIF (Cg_FRAMEWORKS)
FIND_PROGRAM(CG_COMPILER cgc
/usr/bin
/usr/local/bin
DOC "The Cg compiler"
)
ELSE (APPLE)
IF (WIN32)
FIND_PROGRAM( CG_COMPILER cgc
$ENV{CG_BIN_PATH}
$ENV{PROGRAMFILES}/NVIDIA\ Corporation/Cg/bin
$ENV{PROGRAMFILES}/Cg
${PROJECT_SOURCE_DIR}/../Cg
DOC "The Cg Compiler"
)
IF (CG_COMPILER)
GET_FILENAME_COMPONENT(CG_COMPILER_DIR ${CG_COMPILER} PATH)
GET_FILENAME_COMPONENT(CG_COMPILER_SUPER_DIR ${CG_COMPILER_DIR} PATH)
ELSE (CG_COMPILER)
SET (CG_COMPILER_DIR .)
SET (CG_COMPILER_SUPER_DIR ..)
ENDIF (CG_COMPILER)
FIND_PATH( CG_INCLUDE_PATH Cg/cg.h
$ENV{CG_INC_PATH}
$ENV{PROGRAMFILES}/NVIDIA\ Corporation/Cg/include
$ENV{PROGRAMFILES}/Cg
${PROJECT_SOURCE_DIR}/../Cg
${CG_COMPILER_SUPER_DIR}/include
${CG_COMPILER_DIR}
DOC "The directory where Cg/cg.h resides"
)
FIND_LIBRARY( CG_LIBRARY
NAMES Cg
PATHS
$ENV{CG_LIB_PATH}
$ENV{PROGRAMFILES}/NVIDIA\ Corporation/Cg/lib
$ENV{PROGRAMFILES}/Cg
${PROJECT_SOURCE_DIR}/../Cg
${CG_COMPILER_SUPER_DIR}/lib
${CG_COMPILER_DIR}
DOC "The Cg runtime library"
)
FIND_LIBRARY( CG_GL_LIBRARY
NAMES CgGL
PATHS
$ENV{PROGRAMFILES}/NVIDIA\ Corporation/Cg/lib
$ENV{PROGRAMFILES}/Cg
${PROJECT_SOURCE_DIR}/../Cg
${CG_COMPILER_SUPER_DIR}/lib
${CG_COMPILER_DIR}
DOC "The Cg runtime library"
)
ELSE (WIN32)
FIND_PROGRAM( CG_COMPILER cgc
/usr/bin
/usr/local/bin
DOC "The Cg Compiler"
)
GET_FILENAME_COMPONENT(CG_COMPILER_DIR "${CG_COMPILER}" PATH)
GET_FILENAME_COMPONENT(CG_COMPILER_SUPER_DIR "${CG_COMPILER_DIR}" PATH)
FIND_PATH( CG_INCLUDE_PATH Cg/cg.h
/usr/include
/usr/local/include
${CG_COMPILER_SUPER_DIR}/include
DOC "The directory where Cg/cg.h resides"
)
FIND_LIBRARY( CG_LIBRARY Cg
PATHS
/usr/lib64
/usr/lib
/usr/local/lib64
/usr/local/lib
${CG_COMPILER_SUPER_DIR}/lib64
${CG_COMPILER_SUPER_DIR}/lib
DOC "The Cg runtime library"
)
SET(CG_LIBRARY ${CG_LIBRARY} -lpthread)
FIND_LIBRARY( CG_GL_LIBRARY CgGL
PATHS
/usr/lib64
/usr/lib
/usr/local/lib64
/usr/local/lib
${CG_COMPILER_SUPER_DIR}/lib64
${CG_COMPILER_SUPER_DIR}/lib
DOC "The Cg runtime library"
)
ENDIF (WIN32)
ENDIF (APPLE)
IF (CG_INCLUDE_PATH)
SET( CG_FOUND 1 CACHE STRING "Set to 1 if CG is found, 0 otherwise")
ELSE (CG_INCLUDE_PATH)
SET( CG_FOUND 0 CACHE STRING "Set to 1 if CG is found, 0 otherwise")
ENDIF (CG_INCLUDE_PATH)
MARK_AS_ADVANCED( CG_FOUND )
#
# Try to find NVIDIA's Cg compiler, runtime libraries, and include path.
# Once done this will define
#
# CG_FOUND =system has NVIDIA Cg and it can be used.
# CG_INCLUDE_PATH = directory where cg.h resides
# CG_LIBRARY = full path to libCg.so (Cg.DLL on win32)
# CG_GL_LIBRARY = full path to libCgGL.so (CgGL.dll on win32)
# CG_COMPILER = full path to cgc (cgc.exe on win32)
#
# On OSX default to using the framework version of Cg.
IF (APPLE)
INCLUDE(${CMAKE_ROOT}/Modules/CMakeFindFrameworks.cmake)
SET(CG_FRAMEWORK_INCLUDES)
CMAKE_FIND_FRAMEWORKS(Cg)
IF (Cg_FRAMEWORKS)
FOREACH(dir ${Cg_FRAMEWORKS})
SET(CG_FRAMEWORK_INCLUDES ${CG_FRAMEWORK_INCLUDES}
${dir}/Headers ${dir}/PrivateHeaders)
ENDFOREACH(dir)
# Find the include dir
FIND_PATH(CG_INCLUDE_PATH cg.h
${CG_FRAMEWORK_INCLUDES}
)
# Since we are using Cg framework, we must link to it.
# Note, we use weak linking, so that it works even when Cg is not available.
SET(CG_LIBRARY "-weak_framework Cg" CACHE STRING "Cg library")
SET(CG_GL_LIBRARY "-weak_framework Cg" CACHE STRING "Cg GL library")
ENDIF (Cg_FRAMEWORKS)
FIND_PROGRAM(CG_COMPILER cgc
/usr/bin
/usr/local/bin
DOC "The Cg compiler"
)
ELSE (APPLE)
IF (WIN32)
FIND_PROGRAM( CG_COMPILER cgc
$ENV{CG_BIN_PATH}
$ENV{PROGRAMFILES}/NVIDIA\ Corporation/Cg/bin
$ENV{PROGRAMFILES}/Cg
${PROJECT_SOURCE_DIR}/../Cg
DOC "The Cg Compiler"
)
IF (CG_COMPILER)
GET_FILENAME_COMPONENT(CG_COMPILER_DIR ${CG_COMPILER} PATH)
GET_FILENAME_COMPONENT(CG_COMPILER_SUPER_DIR ${CG_COMPILER_DIR} PATH)
ELSE (CG_COMPILER)
SET (CG_COMPILER_DIR .)
SET (CG_COMPILER_SUPER_DIR ..)
ENDIF (CG_COMPILER)
FIND_PATH( CG_INCLUDE_PATH Cg/cg.h
$ENV{CG_INC_PATH}
$ENV{PROGRAMFILES}/NVIDIA\ Corporation/Cg/include
$ENV{PROGRAMFILES}/Cg
${PROJECT_SOURCE_DIR}/../Cg
${CG_COMPILER_SUPER_DIR}/include
${CG_COMPILER_DIR}
DOC "The directory where Cg/cg.h resides"
)
FIND_LIBRARY( CG_LIBRARY
NAMES Cg
PATHS
$ENV{CG_LIB_PATH}
$ENV{PROGRAMFILES}/NVIDIA\ Corporation/Cg/lib
$ENV{PROGRAMFILES}/Cg
${PROJECT_SOURCE_DIR}/../Cg
${CG_COMPILER_SUPER_DIR}/lib
${CG_COMPILER_DIR}
DOC "The Cg runtime library"
)
FIND_LIBRARY( CG_GL_LIBRARY
NAMES CgGL
PATHS
$ENV{PROGRAMFILES}/NVIDIA\ Corporation/Cg/lib
$ENV{PROGRAMFILES}/Cg
${PROJECT_SOURCE_DIR}/../Cg
${CG_COMPILER_SUPER_DIR}/lib
${CG_COMPILER_DIR}
DOC "The Cg runtime library"
)
ELSE (WIN32)
FIND_PROGRAM( CG_COMPILER cgc
/usr/bin
/usr/local/bin
DOC "The Cg Compiler"
)
GET_FILENAME_COMPONENT(CG_COMPILER_DIR "${CG_COMPILER}" PATH)
GET_FILENAME_COMPONENT(CG_COMPILER_SUPER_DIR "${CG_COMPILER_DIR}" PATH)
FIND_PATH( CG_INCLUDE_PATH Cg/cg.h
/usr/include
/usr/local/include
${CG_COMPILER_SUPER_DIR}/include
DOC "The directory where Cg/cg.h resides"
)
FIND_LIBRARY( CG_LIBRARY Cg
PATHS
/usr/lib64
/usr/lib
/usr/local/lib64
/usr/local/lib
${CG_COMPILER_SUPER_DIR}/lib64
${CG_COMPILER_SUPER_DIR}/lib
DOC "The Cg runtime library"
)
SET(CG_LIBRARY ${CG_LIBRARY} -lpthread)
FIND_LIBRARY( CG_GL_LIBRARY CgGL
PATHS
/usr/lib64
/usr/lib
/usr/local/lib64
/usr/local/lib
${CG_COMPILER_SUPER_DIR}/lib64
${CG_COMPILER_SUPER_DIR}/lib
DOC "The Cg runtime library"
)
ENDIF (WIN32)
ENDIF (APPLE)
IF (CG_INCLUDE_PATH)
SET( CG_FOUND 1 CACHE STRING "Set to 1 if CG is found, 0 otherwise")
ELSE (CG_INCLUDE_PATH)
SET( CG_FOUND 0 CACHE STRING "Set to 1 if CG is found, 0 otherwise")
ENDIF (CG_INCLUDE_PATH)
MARK_AS_ADVANCED( CG_FOUND )

@ -0,0 +1,32 @@
IF (WIN32)
FIND_PATH(DX10_INCLUDE_PATH D3D10.h
PATHS
"$ENV{DXSDK_DIR}/Include"
"$ENV{PROGRAMFILES}/Microsoft DirectX SDK/Include"
DOC "The directory where D3D10.h resides")
FIND_LIBRARY(D3D10_LIBRARY d3d10.lib
PATHS
"$ENV{DXSDK_DIR}/Lib/x86"
"$ENV{PROGRAMFILES}/Microsoft DirectX SDK/Lib/x86"
DOC "The directory where d3d10.lib resides")
FIND_LIBRARY(D3DX10_LIBRARY d3dx10.lib
PATHS
"$ENV{DXSDK_DIR}/Lib/x86"
"$ENV{PROGRAMFILES}/Microsoft DirectX SDK/Lib/x86"
DOC "The directory where d3dx10.lib resides")
SET(DX10_LIBRARIES D3D10_LIBRARY D3DX10_LIBRARY)
ENDIF (WIN32)
IF (DX10_INCLUDE_PATH)
SET( DX10_FOUND 1 CACHE STRING "Set to 1 if CG is found, 0 otherwise")
ELSE (DX10_INCLUDE_PATH)
SET( DX10_FOUND 0 CACHE STRING "Set to 1 if CG is found, 0 otherwise")
ENDIF (DX10_INCLUDE_PATH)
MARK_AS_ADVANCED( DX10_FOUND )

@ -0,0 +1,67 @@
IF (WIN32)
# Maya plugins can only be compiled with msvc
IF (MSVC)
FIND_PATH(MAYA_INCLUDE_PATH maya/MTypes.h
PATHS
"$ENV{PROGRAMFILES}/Autodesk/Maya8.5/include"
"$ENV{MAYA_LOCATION}/include"
DOC "The directory where MTypes.h resides")
# Find maya version!
FIND_LIBRARY(MAYA_FOUNDATION_LIBRARY Foundation
PATHS
"$ENV{PROGRAMFILES}/Autodesk/Maya8.5/lib"
"$ENV{MAYA_LOCATION}/lib"
DOC "The directory where Foundation.lib resides")
FIND_LIBRARY(MAYA_OPENMAYA_LIBRARY OpenMaya
PATHS
"$ENV{PROGRAMFILES}/Autodesk/Maya8.5/lib"
"$ENV{MAYA_LOCATION}/lib"
DOC "The directory where OpenMaya.lib resides")
FIND_LIBRARY(MAYA_OPENMAYAANIM_LIBRARY OpenMayaAnim
PATHS
"$ENV{PROGRAMFILES}/Autodesk/Maya8.5/lib"
"$ENV{MAYA_LOCATION}/lib"
DOC "The directory where OpenMayaAnim.lib resides")
SET(MAYA_LIBRARIES
${MAYA_FOUNDATION_LIBRARY}
${MAYA_OPENMAYA_LIBRARY}
${MAYA_OPENMAYAANIM_LIBRARY})
SET(MAYA_EXTENSION ".mll")
ENDIF (MSVC)
ELSE (WIN32)
# On linux, check gcc version.
# OSX and Linux
FIND_PATH(MAYA_INCLUDE_PATH maya/MTypes.h
PATHS
/usr/autodesk/maya/include
$ENV{MAYA_LOCATION}/include
DOC "The directory where MTypes.h resides")
# TODO
ENDIF (WIN32)
IF (MAYA_INCLUDE_PATH)
SET( MAYA_FOUND 1 CACHE STRING "Set to 1 if Maya is found, 0 otherwise")
ELSE (MAYA_INCLUDE_PATH)
SET( MAYA_FOUND 0 CACHE STRING "Set to 1 if Maya is found, 0 otherwise")
ENDIF (MAYA_INCLUDE_PATH)
MARK_AS_ADVANCED( MAYA_FOUND )

@ -0,0 +1,55 @@
#
# Try to find OpenEXR's libraries, and include path.
# Once done this will define:
#
# OPENEXR_FOUND = OpenEXR found.
# OPENEXR_INCLUDE_PATH = OpenEXR include directory.
# OPENEXR_LIBRARIES = libraries that are needed to use OpenEXR.
#
IF (WIN32)
ELSE (WIN32)
FIND_PATH(OPENEXR_INCLUDE_PATH ImfRgbaFile.h
/usr/include
/usr/local/include)
FIND_LIBRARY(OPENEXR_HALF_LIBRARY
NAMES Half
PATHS
/usr/lib
/usr/local/lib)
FIND_LIBRARY(OPENEXR_IEX_LIBRARY
NAMES Iex
PATHS
/usr/lib
/usr/local/lib)
FIND_LIBRARY(OPENEXR_IMATH_LIBRARY
NAMES Imath
PATHS
/usr/lib
/usr/local/lib)
FIND_LIBRARY(OPENEXR_ILMIMF_LIBRARY
NAMES IlmImf
PATHS
/usr/lib
/usr/local/lib)
ENDIF (WIN32)
IF (OPENEXR_INCLUDE_DIR AND OPENEXR_IMATH_LIBRARY AND OPENEXR_ILMIMF_LIBRARY AND OPENEXR_IEX_LIBRARY AND OPENEXR_HALF_LIBRARY)
SET(OPENEXR_FOUND TRUE)
SET(OPENEXR_LIBRARIES ${OPENEXR_IMATH_LIBRARY} ${OPENEXR_ILMIMF_LIBRARY} ${OPENEXR_IEX_LIBRARY} ${OPENEXR_HALF_LIBRARY} CACHE STRING "The libraries needed to use OpenEXR")
ENDIF (OPENEXR_INCLUDE_DIR AND OPENEXR_IMATH_LIBRARY AND OPENEXR_ILMIMF_LIBRARY AND OPENEXR_IEX_LIBRARY AND OPENEXR_HALF_LIBRARY)
MARK_AS_ADVANCED(
OPENEXR_INCLUDE_DIR
OPENEXR_LIBRARIES
OPENEXR_ILMIMF_LIBRARY
OPENEXR_IMATH_LIBRARY
OPENEXR_IEX_LIBRARY
OPENEXR_HALF_LIBRARY)

@ -23,6 +23,14 @@ ELSE(GLUT_FOUND)
MESSAGE(STATUS "Looking for GLUT - not found")
ENDIF(GLUT_FOUND)
# DirectX
INCLUDE(${NV_CMAKE_DIR}/FindDirectX.cmake)
IF(DX10_FOUND)
MESSAGE(STATUS "Looking for DirectX - found")
ELSE(DX10_FOUND)
MESSAGE(STATUS "Looking for DirectX - not found")
ENDIF(DX10_FOUND)
# GLEW
INCLUDE(${NV_CMAKE_DIR}/FindGLEW.cmake)
IF(GLEW_FOUND)
@ -47,6 +55,15 @@ ELSE(CUDA_FOUND)
MESSAGE(STATUS "Looking for CUDA - not found")
ENDIF(CUDA_FOUND)
# Maya
INCLUDE(${NV_CMAKE_DIR}/FindMaya.cmake)
IF(MAYA_FOUND)
SET(HAVE_MAYA MAYA_FOUND)
MESSAGE(STATUS "Looking for Maya - found")
ELSE(MAYA_FOUND)
MESSAGE(STATUS "Looking for Maya - not found")
ENDIF(MAYA_FOUND)
# JPEG
INCLUDE(FindJPEG)
IF(JPEG_FOUND)
@ -74,6 +91,15 @@ ELSE(TIFF_FOUND)
MESSAGE(STATUS "Looking for TIFF - not found")
ENDIF(TIFF_FOUND)
# OpenEXR
INCLUDE(FindOpenEXR)
IF(OPENEXR_FOUND)
SET(HAVE_OPENEXR OPENEXR_FOUND)
MESSAGE(STATUS "Looking for OpenEXR - found")
ELSE(OPENEXR_FOUND)
MESSAGE(STATUS "Looking for OpenEXR - not found")
ENDIF(OPENEXR_FOUND)
# Qt
FIND_PACKAGE(Qt4)

@ -10,5 +10,8 @@
#cmakedefine HAVE_PNG
#cmakedefine HAVE_JPEG
#cmakedefine HAVE_TIFF
#cmakedefine HAVE_OPENEXR
#cmakedefine HAVE_MAYA
#endif // NV_CONFIG

@ -3,6 +3,7 @@ ADD_SUBDIRECTORY(poshlib)
SET(CORE_SRCS
nvcore.h
Ptr.h
BitArray.h
Memory.h
Memory.cpp

@ -283,7 +283,7 @@ namespace nv
else
{
m_size = new_size;
m_buffer[new_size-1] = val;
new(m_buffer+new_size-1) T(val);
}
}
void pushBack( const T & val )

@ -195,7 +195,7 @@ namespace
// Solaris:
// ucp->uc_mcontext.gregs[REG_PC]
// Linux hppa:
// uc->uc_mcontext.sc_iaoq[0] & ~0×3UL
// uc->uc_mcontext.sc_iaoq[0] & ~0x3UL
// Linux sparc:
// ((struct sigcontext*) secret)->sigc_regs.tpc
// Linux sparc64:
@ -204,7 +204,7 @@ namespace
// potentially correct for other archs:
// Linux alpha: ucp->m_context.sc_pc
// Linux arm: ucp->m_context.ctx.arm_pc
// Linux ia64: ucp->m_context.sc_ip & ~0×3UL
// Linux ia64: ucp->m_context.sc_ip & ~0x3UL
// Linux mips: ucp->m_context.sc_pc
// Linux s390: ucp->m_context.sregs->regs.psw.addr
}
@ -257,7 +257,7 @@ namespace
{
bool result = false;
HINSTANCE kern_lib = LoadLibraryEx( "kernel32.dll", NULL, 0 );
HINSTANCE kern_lib = LoadLibraryExA( "kernel32.dll", NULL, 0 );
if( kern_lib ) {
FARPROC lIsDebuggerPresent = GetProcAddress( kern_lib, "IsDebuggerPresent" );
if( lIsDebuggerPresent && lIsDebuggerPresent() ) {
@ -302,7 +302,7 @@ namespace
}
flushMessageQueue();
int action = MessageBox(NULL, error_string, "Assertion failed", MB_ABORTRETRYIGNORE|MB_ICONERROR);
int action = MessageBoxA(NULL, error_string, "Assertion failed", MB_ABORTRETRYIGNORE|MB_ICONERROR);
switch( action ) {
case IDRETRY:
ret = NV_ABORT_DEBUG;

@ -73,6 +73,12 @@ public:
{
return m_fp == NULL || ferror( m_fp ) != 0;
}
virtual void clearError()
{
nvDebugCheck(m_fp != NULL);
clearerr(m_fp);
}
virtual bool isAtEnd() const
{
@ -210,6 +216,11 @@ public:
return m_mem == NULL || m_ptr > m_mem + m_size || m_ptr < m_mem;
}
virtual void clearError()
{
// Nothing to do.
}
virtual bool isAtEnd() const
{
return m_ptr == m_mem + m_size;

@ -9,7 +9,7 @@
namespace nv
{
/** Base stream class. */
/// Base stream class.
class Stream {
public:
@ -41,7 +41,7 @@ public:
ByteOrder byteOrder() const { return m_byteOrder; }
/// Serialize the given data.
/// Serialize the given data. @@ Should return bytes serialized?
virtual void serialize( void * data, int len ) = 0;
/// Move to the given position in the archive.
@ -55,7 +55,10 @@ public:
/// Determine if there has been any error.
virtual bool isError() const = 0;
/// Clear errors.
virtual void clearError() = 0;
/// Return true if the stream is at the end.
virtual bool isAtEnd() const = 0;

@ -49,6 +49,10 @@ namespace nv
int m_column;
};
// @@ Use enums instead of bools for clarity!
//enum SkipEmptyLines { skipEmptyLines, noSkipEmptyLines };
//enum SkipEndOfLine { skipEndOfLine, noSkipEndOfLine };
/// A simple stream tokenizer.
class NVCORE_CLASS Tokenizer
{

@ -87,6 +87,7 @@ public:
float * scanline(uint y, uint c);
void setPixel(float f, uint x, uint y, uint c);
void addPixel(float f, uint x, uint y, uint c);
float pixel(uint x, uint y, uint c) const;
void setPixel(float f, uint idx);
@ -164,6 +165,16 @@ inline void FloatImage::setPixel(float f, uint x, uint y, uint c)
m_mem[(c * m_height + y) * m_width + x] = f;
}
/// Add to pixel component.
inline void FloatImage::addPixel(float f, uint x, uint y, uint c)
{
nvDebugCheck(m_mem != NULL);
nvDebugCheck(x < m_width);
nvDebugCheck(y < m_height);
nvDebugCheck(c < m_componentNum);
m_mem[(c * m_height + y) * m_width + x] += f;
}
/// Get pixel component.
inline float FloatImage::pixel(uint x, uint y, uint c) const
{

@ -29,6 +29,13 @@ extern "C" {
# include <tiffio.h>
#endif
#if defined(HAVE_EXR)
# include <ImfRgbaFile.h>
# include <ImfInputFile.h> // ???
# include <ImfArray.h>
using namespace Imf;
#endif
using namespace nv;
namespace {
@ -80,6 +87,34 @@ Image * nv::ImageIO::load(const char * name, Stream & s)
return loadPSD(s);
}
// @@ use image plugins?
return NULL;
}
NVIMAGE_API FloatImage * nv::ImageIO::loadFloat(const char * name)
{
StdInputStream stream(name);
if (stream.isError()) {
return false;
}
return loadFloat(name, stream);
}
NVIMAGE_API FloatImage * nv::ImageIO::loadFloat(const char * name, Stream & s)
{
const char * extension = Path::extension(name);
#if defined(HAVE_TIFF)
if (strCaseCmp(extension, ".tif") == 0 || strCaseCmp(extension, ".tiff") == 0) {
return loadFloatTIFF(name, s);
}
#endif
#if defined(HAVE_EXR)
if (strCaseCmp(extension, ".exr") == 0) {
return loadFloatEXR(name, s);
}
#endif
return NULL;
}
@ -744,15 +779,73 @@ Image * nv::ImageIO::loadJPG(Stream & s)
#if defined(HAVE_TIFF)
FloatImage * nv::ImageIO::loadFloatTIFF(Stream & s)
static tsize_t tiffReadWriteProc(thandle_t h, tdata_t ptr, tsize_t size)
{
nvCheck(!s.isError());
return NULL;
Stream * s = (Stream *)h;
nvDebugCheck(s != NULL);
s->serialize(ptr, size);
return size;
}
FloatImage * nv::ImageIO::loadFloatTIFF(const char * fileName)
static toff_t tiffSeekProc(thandle_t h, toff_t offset, int whence)
{
Stream * s = (Stream *)h;
nvDebugCheck(s != NULL);
if (!s->isSeekable())
{
return (toff_t)-1;
}
if (whence == SEEK_SET)
{
s->seek(offset);
}
else if (whence == SEEK_CUR)
{
s->seek(s->tell() + offset);
}
else if (whence == SEEK_END)
{
s->seek(s->size() + offset);
}
return s->tell();
}
static int tiffCloseProc(thandle_t)
{
return 0;
}
static toff_t tiffSizeProc(thandle_t h)
{
Stream * s = (Stream *)h;
nvDebugCheck(s != NULL);
return s->size();
}
static int tiffMapFileProc(thandle_t, tdata_t*, toff_t*)
{
// @@ TODO, Implement these functions.
return -1;
}
static void tiffUnmapFileProc(thandle_t, tdata_t, toff_t)
{
// @@ TODO, Implement these functions.
}
FloatImage * nv::ImageIO::loadFloatTIFF(const char * fileName, Stream & s)
{
nvCheck(!s.isError());
TIFF * tif = TIFFOpen(fileName, "r");
//TIFF * tif = TIFFClientOpen(fileName, "r", &s, tiffReadWriteProc, tiffReadWriteProc, tiffSeekProc, tiffCloseProc, tiffSizeProc, tiffMapFileProc, tiffUnmapFileProc);
if (!tif)
{
nvDebug("Can't open '%s' for reading\n", fileName);
@ -821,12 +914,11 @@ FloatImage * nv::ImageIO::loadFloatTIFF(const char * fileName)
return fimage.release();
}
bool nv::ImageIO::saveFloatTIFF(const char * fileName, FloatImage *fimage)
bool nv::ImageIO::saveFloatTIFF(const char * fileName, FloatImage *fimage, uint base_component, uint num_components)
{
int iW=fimage->width();
int iH=fimage->height();
int iC=fimage->componentNum();
int iC=num_components;
TIFF * image = TIFFOpen(fileName, "w");
@ -848,7 +940,6 @@ bool nv::ImageIO::saveFloatTIFF(const char * fileName, FloatImage *fimage)
TIFFSetField(image, TIFFTAG_ROWSPERSTRIP, rowsperstrip);
TIFFSetField(image, TIFFTAG_COMPRESSION, COMPRESSION_PACKBITS);
TIFFSetField(image, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
TIFFSetField(image, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
float *scanline = new float[iW * iC];
@ -856,7 +947,7 @@ bool nv::ImageIO::saveFloatTIFF(const char * fileName, FloatImage *fimage)
{
for (int c=0; c<iC; c++)
{
float *src = fimage->scanline(y, c);
float *src = fimage->scanline(y, base_component + c);
for (int x=0; x<iW; x++) scanline[x*iC+c]=src[x];
}
if (TIFFWriteScanline(image, scanline, y, 0)==-1)
@ -872,9 +963,101 @@ bool nv::ImageIO::saveFloatTIFF(const char * fileName, FloatImage *fimage)
return true;
}
#endif
#if defined(HAVE_EXR)
namespace
{
class ExrStream : public Imf::IStream
{
public:
ExrStream(Stream & s) : m_stream(s)
{
nvDebugCheck(s.isLoading());
}
virtual bool read(char c[], int n)
{
m_stream.serialize(c, n);
if (m_stream.isError())
{
throw Iex::InputExc("I/O error.");
}
return m_stream.isAtEnd();
}
virtual Int64 tellg()
{
return m_stream.tell();
}
virtual void seekg(Int64 pos)
{
m_stream.seek(pos);
}
virtual void clear()
{
m_stream.clearError();
}
private:
Stream & m_stream;
};
} // namespace
FloatImage * nv::ImageIO::loadFloatEXR(const char * fileName, Stream & s)
{
nvCheck(!s.isError());
ExrStream stream(s);
RgbaInputFile inputFile(stream);
Box2i box = inputFile.dataWindow();
int width = box.max.x - box.min.y + 1;
int height = box.max.x - box.min.y + 1;
Array2D<Rgba> pixels;
pixels.resizeErase (height, width);
inputFile.setFrameBuffer (&pixels[0][0] - dw.min.x - dw.min.y * width, 1, width);
inputFile.readPixels (box.min.y, box.max.y);
AutoPtr<FloatImage> fimage(new FloatImage());
fimage->allocate(spp, width, height);
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
fimage->setPixel(imagePixel.r, x, y, 0);
fimage->setPixel(imagePixel.g, x, y, 1);
fimage->setPixel(imagePixel.b, x, y, 2);
fimage->setPixel(imagePixel.a, x, y, 3);
}
}
return fimage.release();
}
FloatImage * nv::ImageIO::loadFloatEXR(const char * fileName)
{
StdInputStream stream(name);
if (stream.isError()) {
return false;
}
return loadFloatExr(fileName, stream);
}
#endif // defined(HAVE_EXR)
#endif
#if 0

@ -13,8 +13,10 @@ namespace nv
namespace ImageIO
{
NVIMAGE_API Image * load(const char * name);
NVIMAGE_API Image * load(const char * name, Stream & s);
NVIMAGE_API Image * load(const char * fileName);
NVIMAGE_API Image * load(const char * fileName, Stream & s);
NVIMAGE_API FloatImage * loadFloat(const char * fileName);
NVIMAGE_API FloatImage * loadFloat(const char * fileName, Stream & s);
NVIMAGE_API Image * loadTGA(Stream & s);
NVIMAGE_API bool saveTGA(Stream & s, const Image * img);
@ -29,13 +31,15 @@ namespace nv
#if defined(HAVE_JPEG)
NVIMAGE_API Image * loadJPG(Stream & s);
#endif
#if defined(HAVE_TIFF)
// Hacks!
NVIMAGE_API FloatImage * loadFloatTIFF(const char * fileName);
NVIMAGE_API bool saveFloatTIFF(const char * fileName, FloatImage *fimage);
NVIMAGE_API FloatImage * loadFloatTIFF(const char * fileName, Stream & s);
NVIMAGE_API bool saveFloatTIFF(const char * fileName, FloatImage *fimage, uint base_component, uint num_components);
#endif
NVIMAGE_API FloatImage * loadFloatTIFF(Stream & s);
#if defined(HAVE_EXR)
NVIMAGE_API FloatImage * loadFloatEXR(const char * fileName, Stream & s);
#endif
} // ImageIO namespace

@ -65,6 +65,17 @@ public:
return (m_maxs - m_mins) * 0.5f;
}
/// Return extents of the box.
scalar extents(uint axis) const
{
nvDebugCheck(axis < 3);
if (axis == 0) return (m_maxs.x() - m_mins.x()) * 0.5f;
if (axis == 1) return (m_maxs.y() - m_mins.y()) * 0.5f;
if (axis == 2) return (m_maxs.z() - m_mins.z()) * 0.5f;
nvAssume(false);
return 0.0f;
}
/// Add a point to this box.
void addPointToBounds(Vector3::Arg p)
{

@ -4,6 +4,7 @@ SET(MATH_SRCS
nvmath.h
Vector.h
Matrix.h
Quaternion.h
Box.h
Color.h
Eigen.h Eigen.cpp
@ -11,7 +12,8 @@ SET(MATH_SRCS
Montecarlo.h Montecarlo.cpp
Random.h Random.cpp
SphericalHarmonic.h SphericalHarmonic.cpp
Basis.h Basis.cpp)
Basis.h Basis.cpp
Triangle.h Triangle.cpp TriBox.cpp)
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})

@ -0,0 +1,128 @@
// This code is in the public domain -- castanyo@yahoo.es
#ifndef NV_MATH_QUATERNION_H
#define NV_MATH_QUATERNION_H
#include <nvmath/nvmath.h>
#include <nvmath/Vector.h>
namespace nv
{
class NVMATH_CLASS Quaternion
{
public:
typedef Quaternion const & Arg;
Quaternion();
explicit Quaternion(zero_t);
Quaternion(float x, float y, float z, float w);
Quaternion(Vector4::Arg v);
const Quaternion & operator=(Quaternion::Arg v);
scalar x() const;
scalar y() const;
scalar z() const;
scalar w() const;
const Vector4 & asVector() const;
Vector4 & asVector();
private:
Vector4 q;
};
inline Quaternion::Quaternion() {}
inline Quaternion::Quaternion(zero_t) : q(zero) {}
inline Quaternion::Quaternion(float x, float y, float z, float w) : q(x, y, z, w) {}
inline Quaternion::Quaternion(Vector4::Arg v) : q(v) {}
inline const Quaternion & Quaternion::operator=(Quaternion::Arg v) { q = v.q; return *this; }
inline scalar Quaternion::x() const { return q.x(); }
inline scalar Quaternion::y() const { return q.y(); }
inline scalar Quaternion::z() const { return q.z(); }
inline scalar Quaternion::w() const { return q.w(); }
inline const Vector4 & Quaternion::asVector() const { return q; }
inline Vector4 & Quaternion::asVector() { return q; }
inline Quaternion mul(Quaternion::Arg a, Quaternion::Arg b)
{
// @@ Efficient SIMD implementation?
return Quaternion(
+ a.x() * b.w() + a.y()*b.z() - a.z()*b.y() + a.w()*b.x(),
- a.x() * b.z() + a.y()*b.w() + a.z()*b.x() + a.w()*b.y(),
+ a.x() * b.y() - a.y()*b.x() + a.z()*b.w() + a.w()*b.z(),
- a.x() * b.x() - a.y()*b.y() - a.z()*b.z() + a.w()*b.w());
}
inline Quaternion scale(Quaternion::Arg q, float s)
{
return scale(q.asVector(), s);
}
inline Quaternion operator *(Quaternion::Arg q, float s)
{
return scale(q, s);
}
inline Quaternion operator *(float s, Quaternion::Arg q)
{
return scale(q, s);
}
inline Quaternion scale(Quaternion::Arg q, Vector4::Arg s)
{
return scale(q.asVector(), s);
}
inline Quaternion operator *(Quaternion::Arg q, Vector4::Arg s)
{
return scale(q, s);
}
inline Quaternion operator *(Vector4::Arg s, Quaternion::Arg q)
{
return scale(q, s);
}
inline Quaternion conjugate(Quaternion::Arg q)
{
return q * Vector4(-1, -1, -1, 1);
}
inline float length(Quaternion::Arg q)
{
return length(q.asVector());
}
inline bool isNormalized(Quaternion::Arg q, float epsilon = NV_NORMAL_EPSILON)
{
return equal(length(q), 1, epsilon);
}
inline Quaternion normalize(Quaternion::Arg q, float epsilon = NV_EPSILON)
{
float l = length(q);
nvDebugCheck(!isZero(l, epsilon));
Quaternion n = scale(q, 1.0f / l);
nvDebugCheck(isNormalized(n));
return n;
}
inline Quaternion inverse(Quaternion::Arg q)
{
return conjugate(normalize(q));
}
/// Create a rotation quaternion for @a angle alpha around normal vector @a v.
inline Quaternion axisAngle(Vector3::Arg v, float alpha)
{
float s = sinf(alpha * 0.5f);
float c = cosf(alpha * 0.5f);
return Quaternion(Vector4(v * s, c));
}
} // nv namespace
#endif // NV_MATH_QUATERNION_H

@ -0,0 +1,226 @@
/********************************************************/
/* AABB-triangle overlap test code */
/* by Tomas Akenine-Möller */
/* Function: int triBoxOverlap(float boxcenter[3], */
/* float boxhalfsize[3],float triverts[3][3]); */
/* History: */
/* 2001-03-05: released the code in its first version */
/* 2001-06-18: changed the order of the tests, faster */
/* */
/* Acknowledgement: Many thanks to Pierre Terdiman for */
/* suggestions and discussions on how to optimize code. */
/* Thanks to David Hunt for finding a ">="-bug! */
/********************************************************/
#include <nvmath/Vector.h>
//#include <nvmath/Triangle.h>
using namespace nv;
#define X 0
#define Y 1
#define Z 2
#define FINDMINMAX(x0,x1,x2,min,max) \
min = max = x0; \
if(x1<min) min=x1;\
if(x1>max) max=x1;\
if(x2<min) min=x2;\
if(x2>max) max=x2;
static bool planeBoxOverlap(Vector3::Arg normal, Vector3::Arg vert, Vector3::Arg maxbox) // -NJMP-
{
Vector3 vmin, vmax;
float signs[3] = {1, 1, 1};
if (normal.x() <= 0.0f) signs[0] = -1;
if (normal.y() <= 0.0f) signs[1] = -1;
if (normal.z() <= 0.0f) signs[2] = -1;
Vector3 sign(signs[0], signs[1], signs[2]);
vmin = -scale(sign, maxbox) - vert;
vmax = scale(sign, maxbox) - vert;
if (dot(normal, vmin) > 0.0f) return false;
if (dot(normal, vmax) >= 0.0f) return true;
return false;
}
/*======================== X-tests ========================*/
#define AXISTEST_X01(a, b, fa, fb) \
p0 = a*v0.y() - b*v0.z(); \
p2 = a*v2.y() - b*v2.z(); \
if(p0<p2) {min=p0; max=p2;} else {min=p2; max=p0;} \
rad = fa * boxhalfsize.y() + fb * boxhalfsize.z(); \
if(min>rad || max<-rad) return false;
#define AXISTEST_X2(a, b, fa, fb) \
p0 = a*v0.y() - b*v0.z(); \
p1 = a*v1.y() - b*v1.z(); \
if(p0<p1) {min=p0; max=p1;} else {min=p1; max=p0;} \
rad = fa * boxhalfsize.y() + fb * boxhalfsize.z(); \
if(min>rad || max<-rad) return false;
/*======================== Y-tests ========================*/
#define AXISTEST_Y02(a, b, fa, fb) \
p0 = -a*v0.x() + b*v0.z(); \
p2 = -a*v2.x() + b*v2.z(); \
if(p0<p2) {min=p0; max=p2;} else {min=p2; max=p0;} \
rad = fa * boxhalfsize.x() + fb * boxhalfsize.z(); \
if(min>rad || max<-rad) return false;
#define AXISTEST_Y1(a, b, fa, fb) \
p0 = -a*v0.x() + b*v0.z(); \
p1 = -a*v1.x() + b*v1.z(); \
if(p0<p1) {min=p0; max=p1;} else {min=p1; max=p0;} \
rad = fa * boxhalfsize.x() + fb * boxhalfsize.z(); \
if(min>rad || max<-rad) return false;
/*======================== Z-tests ========================*/
#define AXISTEST_Z12(a, b, fa, fb) \
p1 = a*v1.x() - b*v1.y(); \
p2 = a*v2.x() - b*v2.y(); \
if(p2<p1) {min=p2; max=p1;} else {min=p1; max=p2;} \
rad = fa * boxhalfsize.x() + fb * boxhalfsize.y(); \
if(min>rad || max<-rad) return false;
#define AXISTEST_Z0(a, b, fa, fb) \
p0 = a*v0.x() - b*v0.y(); \
p1 = a*v1.x() - b*v1.y(); \
if(p0<p1) {min=p0; max=p1;} else {min=p1; max=p0;} \
rad = fa * boxhalfsize.x() + fb * boxhalfsize.y(); \
if(min>rad || max<-rad) return false;
bool triBoxOverlap(Vector3::Arg boxcenter, Vector3::Arg boxhalfsize, const Vector3 * triverts)
{
// use separating axis theorem to test overlap between triangle and box
// need to test for overlap in these directions:
// 1) the {x,y,z}-directions (actually, since we use the AABB of the triangle
// we do not even need to test these)
// 2) normal of the triangle
// 3) crossproduct(edge from tri, {x,y,z}-directin)
// this gives 3x3=9 more tests
Vector3 v0, v1, v2;
float min, max, p0, p1, p2, rad, fex, fey, fez;
Vector3 normal, e0, e1, e2;
// This is the fastest branch on Sun.
// move everything so that the boxcenter is in (0,0,0)
v0 = triverts[0] - boxcenter;
v1 = triverts[1] - boxcenter;
v2 = triverts[2] - boxcenter;
// Compute triangle edges.
e0 = v1 - v0; // tri edge 0
e1 = v2 - v1; // tri edge 1
e2 = v0 - v2; // tri edge 2
// Bullet 3:
// test the 9 tests first (this was faster)
fex = fabsf(e0.x());
fey = fabsf(e0.y());
fez = fabsf(e0.z());
AXISTEST_X01(e0.z(), e0.y(), fez, fey);
AXISTEST_Y02(e0.z(), e0.x(), fez, fex);
AXISTEST_Z12(e0.y(), e0.x(), fey, fex);
fex = fabsf(e1.x());
fey = fabsf(e1.y());
fez = fabsf(e1.z());
AXISTEST_X01(e1.z(), e1.y(), fez, fey);
AXISTEST_Y02(e1.z(), e1.x(), fez, fex);
AXISTEST_Z0(e1.y(), e1.x(), fey, fex);
fex = fabsf(e2.x());
fey = fabsf(e2.y());
fez = fabsf(e2.z());
AXISTEST_X2(e2.z(), e2.y(), fez, fey);
AXISTEST_Y1(e2.z(), e2.x(), fez, fex);
AXISTEST_Z12(e2.y(), e2.x(), fey, fex);
// Bullet 1:
// first test overlap in the {x,y,z}-directions
// find min, max of the triangle each direction, and test for overlap in
// that direction -- this is equivalent to testing a minimal AABB around
// the triangle against the AABB
// test in X-direction
FINDMINMAX(v0.x(), v1.x(), v2.x(), min, max);
if(min > boxhalfsize.x() || max < -boxhalfsize.x()) return false;
// test in Y-direction
FINDMINMAX(v0.y(), v1.y(), v2.y(), min, max);
if(min > boxhalfsize.y() || max < -boxhalfsize.y()) return false;
// test in Z-direction
FINDMINMAX(v0.z(), v1.z(), v2.z(), min, max);
if(min > boxhalfsize.z() || max < -boxhalfsize.z()) return false;
// Bullet 2:
// test if the box intersects the plane of the triangle
// compute plane equation of triangle: normal*x+d=0
normal = cross(e0, e1);
return planeBoxOverlap(normal, v0, boxhalfsize);
}
bool triBoxOverlapNoBounds(Vector3::Arg boxcenter, Vector3::Arg boxhalfsize, const Vector3 * triverts)
{
// use separating axis theorem to test overlap between triangle and box
// need to test for overlap in these directions:
// 1) the {x,y,z}-directions (actually, since we use the AABB of the triangle
// we do not even need to test these)
// 2) normal of the triangle
// 3) crossproduct(edge from tri, {x,y,z}-directin)
// this gives 3x3=9 more tests
Vector3 v0, v1, v2;
float min, max, p0, p1, p2, rad, fex, fey, fez;
Vector3 normal, e0, e1, e2;
// This is the fastest branch on Sun.
// move everything so that the boxcenter is in (0,0,0)
v0 = triverts[0] - boxcenter;
v1 = triverts[1] - boxcenter;
v2 = triverts[2] - boxcenter;
// Compute triangle edges.
e0 = v1 - v0; // tri edge 0
e1 = v2 - v1; // tri edge 1
e2 = v0 - v2; // tri edge 2
// Bullet 3:
// test the 9 tests first (this was faster)
fex = fabsf(e0.x());
fey = fabsf(e0.y());
fez = fabsf(e0.z());
AXISTEST_X01(e0.z(), e0.y(), fez, fey);
AXISTEST_Y02(e0.z(), e0.x(), fez, fex);
AXISTEST_Z12(e0.y(), e0.x(), fey, fex);
fex = fabsf(e1.x());
fey = fabsf(e1.y());
fez = fabsf(e1.z());
AXISTEST_X01(e1.z(), e1.y(), fez, fey);
AXISTEST_Y02(e1.z(), e1.x(), fez, fex);
AXISTEST_Z0(e1.y(), e1.x(), fey, fex);
fex = fabsf(e2.x());
fey = fabsf(e2.y());
fez = fabsf(e2.z());
AXISTEST_X2(e2.z(), e2.y(), fez, fey);
AXISTEST_Y1(e2.z(), e2.x(), fez, fex);
AXISTEST_Z12(e2.y(), e2.x(), fey, fex);
// Bullet 2:
// test if the box intersects the plane of the triangle
// compute plane equation of triangle: normal*x+d=0
normal = cross(e0, e1);
return planeBoxOverlap(normal, v0, boxhalfsize);
}

@ -0,0 +1,171 @@
// This code is in the public domain -- Ignacio Castaño <castanyo@yahoo.es>
#include <nvmath/Triangle.h>
using namespace nv;
/// Tomas Möller, barycentric ray-triangle test.
bool Triangle::TestRay_Moller(Vector3::Arg orig, Vector3::Arg dir, float * out_t, float * out_u, float * out_v)
{
Vector3 e1, e2, tvec, pvec, qvec;
float det, inv_det;
// find vectors for two edges sharing vert0
e1 = v[1] - v[0];
e2 = v[2] - v[0];
// begin calculating determinant - also used to calculate U parameter
pvec = cross(dir, e2);
// if determinant is near zero, ray lies in plane of triangle
det = dot(e1, pvec);
if (det < -NV_EPSILON) {
return false;
}
// calculate distance from vert0 to ray origin
tvec = orig - v[0];
// calculate U parameter and test bounds
float u = dot(tvec, pvec);
if( u < 0.0f || u > det ) {
return false;
}
// prepare to test V parameter
qvec = cross(tvec, e1);
// calculate V parameter and test bounds
float v = dot(dir, qvec);
if (v < 0.0f || u + v > det) {
return false;
}
// calculate t, scale parameters, ray intersects triangle
inv_det = 1.0f / det;
*out_t = dot(e2, qvec) * inv_det;
*out_u = u * inv_det; // v
*out_v = v * inv_det; // 1-(u+v)
return true;
}
#if 0
// IC: This code is adapted from my Pi.MathLib code, based on Moller-Trumbore triangle test.
FXVector3 edge1, edge2, pvec, tvec, qvec;
edge1 = tri.V1 - tri.V0;
edge2 = tri.V2 - tri.V0;
pvec.Cross(ray.Direction, edge2);
float det = FXVector3.Dot(edge1, pvec);
// calculate distance from vert0 to ray origin.
FXVector3 tvec = ray.Origin - vert0;
if( det < 0 )
{
// calculate U parameter and test bounds.
float u = FXVector3.Dot(tvec, pvec);
if (u > 0.0 || u < det)
{
return false;
}
// prepare to test V parameter.
qvec.Cross(tvec, edge1);
// calculate V parameter and test bounds.
float v = FXVector3.Dot(dir, qvec);
return v <= 0.0 && u + v >= det;
}
else
{
// calculate U parameter and test bounds.
float u = FXVector3.Dot(tvec, pvec);
if (u < 0.0 || u > det)
{
return false;
}
// prepare to test V parameter.
qvec.Cross(tvec, edge1);
// calculate V parameter and test bounds.
float v = FXVector3.Dot(dir, qvec);
return v >= 0.0 && u + v <= det;
}
/**
* Dan Sunday, parametric ray-triangle test.
*/
// Output: *I = intersection point (when it exists)
// Return: -1 = triangle is degenerate (a segment or point)
// 0 = disjoint (no intersect)
// 1 = intersect in unique point I1
// 2 = are in the same plane
bool RayTriangleTest( const Vec3 &p0, const Vec3 &p1,
const Vec3 &v0, const Vec3 &v1, const Vec3 &v2, const Vec3 &n,
Vec3 &I ) {
Vec3 u, v; // triangle vectors
Vec3 dir, w0, w; // ray vectors
float r, a, b; // params to calc ray-plane intersect
// get triangle edge vectors and plane normal
u.Sub( v1, v0 );
v.Sub( v2, v0 );
dir.Sub( p1, p0 ); // ray direction vector
w0.Sub( p0, v0 );
a = Vec3DotProduct( n, w0 );
b = Vec3DotProduct( n, dir );
if( fabs(b) < TI_EPSILON ) // ray is parallel to triangle plane
return false;
// get intersect point of ray with triangle plane
r = -a / b;
if( r < 0.0f ) // ray goes away from triangle
return false; // => no intersect
// for a segment, also test if (r > 1.0) => no intersect
I.Mad( p0, dir, r ); // intersect point of ray and plane
// is I inside T?
float uu, uv, vv, wu, wv, D;
uu = Vec3DotProduct( u, u );
uv = Vec3DotProduct( u, v );
vv = Vec3DotProduct( v, v );
w = I - v0;
wu = Vec3DotProduct( w, u );
wv = Vec3DotProduct( w, v );
D = uv * uv - uu * vv;
// get and test parametric coords
float s, t;
s = (uv * wv - vv * wu) / D;
if( s<0.0 || s > 1.0) // I is outside T
return false;
t = (uv * wu - uu * wv) / D;
if( t<0.0 || (s + t) > 1.0) // I is outside T
return false;
return true; // I is in T
}
#endif // 0

@ -0,0 +1,149 @@
// This code is in the public domain -- Ignacio Castaño <castanyo@yahoo.es>
#ifndef NV_MATH_TRIANGLE_H
#define NV_MATH_TRIANGLE_H
#include <nvmath/nvmath.h>
#include <nvmath/Vector.h>
#include <nvmath/Box.h>
//#include <nvmath/Plane.h>
namespace nv
{
// Tomas Akenine-Möller box-triangle test.
NVMATH_API bool triBoxOverlap(Vector3::Arg boxcenter, Vector3::Arg boxhalfsize, const Vector3 * restrict triverts);
NVMATH_API bool triBoxOverlapNoBounds(Vector3::Arg boxcenter, Vector3::Arg boxhalfsize, const Vector3 * restrict triverts);
/// Triangle class with three vertices.
class Triangle
{
public:
Triangle() {};
Triangle(const Vector3 & v0, const Vector3 & v1, const Vector3 & v2)
{
v[0] = v0;
v[1] = v1;
v[2] = v2;
}
/// Get the bounds of the triangle.
Box bounds() const {
Box bounds;
bounds.clearBounds();
bounds.addPointToBounds(v[0]);
bounds.addPointToBounds(v[1]);
bounds.addPointToBounds(v[2]);
return bounds;
}
/*
/// Get barycentric coordinates of the given point in this triangle.
Vector3 barycentricCoordinates(Vector3::Arg p)
{
Vector3 bar;
// p must lie in the triangle plane.
Plane plane;
plane.set(v[0], v[1], v[2]);
nvCheck( equalf(plane.Distance(p), 0.0f) );
Vector3 n;
// Compute signed area of triangle <v0, v1, p>
n = cross(v[1] - v[0], p - v[0]);
bar.x = length(n);
if (dot(n, plane.vector) < 0) {
bar->x = -bar->x;
}
// Compute signed area of triangle <v1, v2, p>
n = cross(v[2] - v[1], p - v[1]);
bar->y = length(cross(e, d));
if (dot(n, plane.vector) < 0) {
bar->y = -bar->y;
}
// Compute signed area of triangle <v2, v0, p>
n = cross(v[0] - v[2], p - v[2]);
bar->z = length(n);
if (dot(n, plane.vector) < 0) {
bar->z = -bar->z;
}
// We cannot just do this because we need the signed areas.
// bar->x = Vector3Area(e0, d0);
// bar->y = Vector3Area(e1, d1);
// bar->z = Vector3Area(e2, d2);
// bar->x = Vector3TripleProduct(v[1], v[2], p);
// bar->y = Vector3TripleProduct(v[2], v[0], p);
// bar->z = Vector3TripleProduct(v[0], v[1], p);
}
*/
// Moller ray triangle test.
bool TestRay_Moller(const Vector3 & orig, const Vector3 & dir, float * out_t, float * out_u, float * out_v);
Vector3 v[3];
};
#if 0
/** A planar triangle. */
class Triangle2 {
public:
Triangle2() {};
Triangle2(const Vec2 & v0, const Vec2 & v1, const Vec2 & v2) {
v[0] = v0;
v[1] = v1;
v[2] = v2;
}
/** Get the barycentric coordinates of the given point for this triangle.
* http://stevehollasch.com/cgindex/math/barycentric.html
*/
void GetBarycentricCoordinates(const Vec2 & p, Vector3 * bar) const {
float denom = 1.0f / (v[1].x - v[0].x) * (v[2].y - v[0].y) - (v[2].x - v[0].x) * (v[1].y - v[0].y);
bar->x = ((v[1].x - p.x) * (v[2].y - p.y) - (v[2].x - p.x) * (v[1].y - p.y)) * denom;
bar->y = ((v[2].x - p.x) * (v[0].y - p.y) - (v[0].x - p.x) * (v[2].y - p.y)) * denom;
//bar->z = ((v[0].x - p.x) * (v[1].y - p.y) - (v[1].x - p.x) * (v[0].y - p.y)) * denom;
bar->z = 1 - bar->x - bar->y;
}
Vec2 v[3];
};
#endif // 0
inline bool overlap(const Triangle & t, const Box & b)
{
Vector3 center = b.center();
Vector3 extents = b.extents();
return triBoxOverlap(center, extents, t.v);
}
inline bool Overlap(const Box & b, const Triangle & t)
{
return overlap(t, b);
}
inline bool overlapNoBounds(const Triangle & t, const Box & b)
{
Vector3 center = b.center();
Vector3 extents = b.extents();
return triBoxOverlapNoBounds(center, extents, t.v);
}
} // nv namespace
#endif // NV_MATH_TRIANGLE_H

@ -22,6 +22,7 @@ public:
Vector2();
explicit Vector2(zero_t);
explicit Vector2(scalar f);
Vector2(scalar x, scalar y);
Vector2(Vector2::Arg v);
@ -29,7 +30,9 @@ public:
scalar x() const;
scalar y() const;
scalar component(uint idx) const;
const scalar * ptr() const;
void set(scalar x, scalar y);
@ -42,7 +45,7 @@ public:
friend bool operator==(Vector2::Arg a, Vector2::Arg b);
friend bool operator!=(Vector2::Arg a, Vector2::Arg b);
private:
scalar m_x, m_y;
};
@ -66,7 +69,9 @@ public:
scalar z() const;
const Vector2 & xy() const;
scalar component(uint idx) const;
// @@ temporary... should use an explicit method?
const scalar * ptr() const;
@ -76,6 +81,7 @@ public:
void operator+=(Vector3::Arg v);
void operator-=(Vector3::Arg v);
void operator*=(scalar s);
void operator/=(scalar s);
void operator*=(Vector3::Arg v);
friend bool operator==(Vector3::Arg a, Vector3::Arg b);
@ -108,7 +114,12 @@ public:
const Vector2 & xy() const;
const Vector3 & xyz() const;
scalar component(uint idx) const;
// @@ temporary... should use an explicit method?
const scalar * ptr() const;
void set(scalar x, scalar y, scalar z, scalar w);
Vector4 operator-() const;
@ -129,6 +140,7 @@ private:
inline Vector2::Vector2() {}
inline Vector2::Vector2(zero_t) : m_x(0.0f), m_y(0.0f) {}
inline Vector2::Vector2(scalar f) : m_x(f), m_y(f) {}
inline Vector2::Vector2(scalar x, scalar y) : m_x(x), m_y(y) {}
inline Vector2::Vector2(Vector2::Arg v) : m_x(v.x()), m_y(v.y()) {}
@ -142,6 +154,15 @@ inline const Vector2 & Vector2::operator=(Vector2::Arg v)
inline scalar Vector2::x() const { return m_x; }
inline scalar Vector2::y() const { return m_y; }
inline scalar Vector2::component(uint idx) const
{
nvDebugCheck(idx < 2);
if (idx == 0) return x();
if (idx == 1) return y();
nvAssume(false);
return 0.0f;
}
inline const scalar * Vector2::ptr() const
{
return &m_x;
@ -216,12 +237,21 @@ inline const Vector2 & Vector3::xy() const
{
return *(Vector2 *)this;
}
inline scalar Vector3::component(uint idx) const
{
nvDebugCheck(idx < 3);
if (idx == 0) return x();
if (idx == 1) return y();
if (idx == 2) return z();
nvAssume(false);
return 0.0f;
}
inline const scalar * Vector3::ptr() const
{
return &m_x;
}
inline void Vector3::set(scalar x, scalar y, scalar z)
{
@ -256,6 +286,14 @@ inline void Vector3::operator*=(scalar s)
m_z *= s;
}
inline void Vector3::operator/=(scalar s)
{
float is = 1.0f / s;
m_x *= is;
m_y *= is;
m_z *= is;
}
inline void Vector3::operator*=(Vector3::Arg v)
{
m_x *= v.m_x;
@ -306,6 +344,17 @@ inline const Vector3 & Vector4::xyz() const
return *(Vector3 *)this;
}
inline scalar Vector4::component(uint idx) const
{
nvDebugCheck(idx < 4);
if (idx == 0) return x();
if (idx == 1) return y();
if (idx == 2) return z();
if (idx == 3) return w();
nvAssume(false);
return 0.0f;
}
inline void Vector4::set(scalar x, scalar y, scalar z, scalar w)
{
m_x = x;
@ -385,7 +434,6 @@ inline Vector2 operator-(Vector2::Arg a, Vector2::Arg b)
return sub(a, b);
}
inline Vector2 scale(Vector2::Arg v, scalar s)
{
return Vector2(v.x() * s, v.y() * s);
@ -508,6 +556,11 @@ inline Vector3 operator*(scalar s, Vector3::Arg v)
return scale(v, s);
}
inline Vector3 operator*(Vector3::Arg v, Vector3::Arg s)
{
return scale(v, s);
}
inline Vector3 operator/(Vector3::Arg v, scalar s)
{
return scale(v, 1.0f/s);

Loading…
Cancel
Save